├── .nvmrc ├── .solhintignore ├── script └── deployment │ ├── test │ ├── README.md │ └── child │ │ ├── DeploySystem.s.sol │ │ ├── DeployL2StateSender.s.sol │ │ ├── DeployStateReceiver.s.sol │ │ ├── DeployChildERC1155.s.sol │ │ ├── DeployChildERC721.s.sol │ │ ├── DeployEIP1559Burn.s.sol │ │ ├── DeployChildERC20.s.sol │ │ ├── validator │ │ ├── DeployRewardPool.s.sol │ │ └── DeployValidatorSet.s.sol │ │ ├── DeployNativeERC20.s.sol │ │ ├── DeployChildERC721Predicate.s.sol │ │ ├── DeployChildERC1155Predicate.s.sol │ │ ├── DeployRootMintableERC20Predicate.s.sol │ │ ├── DeployRootMintableERC721Predicate.s.sol │ │ ├── DeployRootMintableERC1155Predicate.s.sol │ │ ├── DeployNativeERC20Mintable.s.sol │ │ ├── DeployChildERC20Predicate.s.sol │ │ ├── DeployChildERC721PredicateAccessList.s.sol │ │ └── DeployChildERC1155PredicateAccessList.s.sol │ ├── sharedRootContractsConfig.json │ ├── rootContractSetConfig.json │ ├── common │ ├── DeployBLS.s.sol │ └── DeployBN256G2.s.sol │ ├── root │ ├── DeployStateSender.s.sol │ ├── staking │ │ ├── DeployStakeManager.s.sol │ │ └── DeployCustomSupernetManager.s.sol │ ├── DeployExitHelper.s.sol │ ├── DeployRootERC721Predicate.s.sol │ ├── DeployRootERC1155Predicate.s.sol │ ├── DeployChildMintableERC20Predicate.s.sol │ ├── DeployChildMintableERC721Predicate.s.sol │ ├── DeployChildMintableERC1155Predicate.s.sol │ ├── DeployRootERC20Predicate.s.sol │ └── DeployCheckpointManager.s.sol │ ├── rootTokenContractsConfig.json │ ├── DeploySharedRootContracts.sol │ └── DeployNewRootContractSet.s.sol ├── .eslintignore ├── types └── index.d.ts ├── .solcover.js ├── docs ├── lib │ ├── GenesisLib.md │ ├── SafeMathInt.md │ ├── SafeMathUint.md │ ├── WithdrawalQueueLib.md │ ├── ModexpSqrt.md │ ├── ModexpInverse.md │ ├── EIP712Upgradeable.md │ ├── EIP712MetaTransaction.md │ └── GenesisProxy.md ├── common │ └── Merkle.md ├── root │ ├── staking │ │ ├── StakeManagerStakingData.md │ │ ├── StakeManagerChildData.md │ │ └── SupernetManager.md │ └── StateSender.md ├── interfaces │ ├── IStateSender.md │ ├── child │ │ ├── IStateReceiver.md │ │ ├── IChildERC20Predicate.md │ │ ├── IChildERC1155Predicate.md │ │ ├── validator │ │ │ └── IRewardPool.md │ │ └── IChildERC721Predicate.md │ ├── IAddressList.md │ ├── root │ │ ├── IL2StateReceiver.md │ │ ├── staking │ │ │ └── ISupernetManager.md │ │ ├── IExitHelper.md │ │ └── IRootValidatorSet.md │ └── common │ │ └── IBN256G2.md └── child │ ├── L2StateSender.md │ ├── EIP1559Burn.md │ └── System.md ├── slither.config.json ├── contracts ├── interfaces │ ├── lib │ │ ├── IRewardPool.sol │ │ ├── IValidatorStorage.sol │ │ ├── IWithdrawalQueue.sol │ │ └── IValidatorQueue.sol │ ├── IStateSender.sol │ ├── IAddressList.sol │ ├── Errors.sol │ ├── child │ │ ├── IStateReceiver.sol │ │ ├── IChildERC1155Predicate.sol │ │ ├── IChildERC20Predicate.sol │ │ ├── IChildERC721Predicate.sol │ │ ├── validator │ │ │ └── IRewardPool.sol │ │ ├── IRootMintableERC20Predicate.sol │ │ ├── IChildERC20.sol │ │ ├── INativeERC20.sol │ │ └── IChildERC721.sol │ ├── root │ │ ├── IL2StateReceiver.sol │ │ ├── IRootValidatorSet.sol │ │ ├── staking │ │ │ ├── ISupernetManager.sol │ │ │ ├── IStakeManager.sol │ │ │ └── ICustomSupernetManager.sol │ │ ├── IChildMintableERC20Predicate.sol │ │ ├── IExitHelper.sol │ │ ├── IChildMintableERC1155Predicate.sol │ │ ├── IChildMintableERC721Predicate.sol │ │ └── IRootERC20Predicate.sol │ └── common │ │ └── IBN256G2.sol ├── mocks │ ├── MockERC20.sol │ ├── MockERC1155.sol │ ├── MockERC721.sol │ ├── StateReceivingContract.sol │ ├── MockNativeERC20Transfer.sol │ ├── MockSupernetManager.sol │ └── MockClones.sol ├── root │ ├── staking │ │ ├── README.md │ │ ├── SupernetManager.sol │ │ ├── StakeManagerStakingData.sol │ │ └── StakeManagerChildData.sol │ ├── StateSender.sol │ └── README.md ├── child │ ├── validator │ │ └── README.md │ ├── System.sol │ ├── L2StateSender.sol │ ├── ChildERC721PredicateAccessList.sol │ ├── ChildERC1155PredicateAccessList.sol │ ├── RootMintableERC20PredicateAccessList.sol │ ├── RootMintableERC721PredicateAccessList.sol │ ├── RootMintableERC1155PredicateAccessList.sol │ ├── ChildERC20PredicateAccessList.sol │ └── EIP1559Burn.sol ├── lib │ ├── SafeMathInt.sol │ ├── README.md │ ├── GenesisProxy.sol │ └── AccessList.sol └── common │ └── README.md ├── .github └── dependabot.yml ├── .husky └── pre-commit ├── .solhint.json ├── .gitmodules ├── .prettierignore ├── tsconfig.json ├── test ├── constants.ts ├── forge │ ├── utils │ │ ├── Test.sol │ │ ├── Cheats.sol │ │ └── Assertions.sol │ ├── root │ │ ├── deployment │ │ │ ├── DeployStateSender.t.sol │ │ │ └── DeployExitHelper.t.sol │ │ ├── generateMsgSupernetManager.ts │ │ ├── StateSender.t.sol │ │ └── staking │ │ │ └── deployment │ │ │ └── DeployStakeManager.t.sol │ ├── child │ │ ├── ChildERC20Predicate.t.sol │ │ ├── ChildERC20.t.sol │ │ ├── ChildERC721.t.sol │ │ ├── ChildERC1155.t.sol │ │ └── generateMsg.ts │ └── libs │ │ └── SafeMathInt.t.sol ├── lib │ └── AccessList.test.ts ├── child │ └── L2StateSender.test.ts └── common │ └── BN256G2.test.ts ├── .prettierrc ├── ts ├── utils.ts └── hashToField.ts ├── foundry.toml ├── .eslintrc.js ├── LICENSE ├── .env.example ├── hardhat.config.ts ├── .gitignore ├── .npmignore └── package.json /.nvmrc: -------------------------------------------------------------------------------- 1 | v16.17.0 2 | -------------------------------------------------------------------------------- /.solhintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | contracts/mocks -------------------------------------------------------------------------------- /script/deployment/test/README.md: -------------------------------------------------------------------------------- 1 | **For testing purposes only!** 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage 5 | typechain 6 | forge 7 | -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/herumi/mcl-wasm/issues/19 2 | declare module "mcl-wasm"; 3 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | configureYulOptimizer: true, 3 | skipFiles: ["mocks"], 4 | }; 5 | -------------------------------------------------------------------------------- /docs/lib/GenesisLib.md: -------------------------------------------------------------------------------- 1 | # GenesisLib 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/lib/SafeMathInt.md: -------------------------------------------------------------------------------- 1 | # SafeMathInt 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/lib/SafeMathUint.md: -------------------------------------------------------------------------------- 1 | # SafeMathUint 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /slither.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "detectors_to_exclude": "solc-version", 3 | "filter_paths": "BLS.sol|ModExp.sol|node_modules|mocks|legacy-compat" 4 | } 5 | -------------------------------------------------------------------------------- /contracts/interfaces/lib/IRewardPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | error NoTokensDelegated(address validator); 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | target-branch: "dev" 8 | -------------------------------------------------------------------------------- /script/deployment/sharedRootContractsConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ProxyAdmin": { 3 | "proxyAdminOwner": "" 4 | }, 5 | 6 | "StakeManager": { 7 | "newStakingToken": "" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | export NVM_DIR="$HOME/.nvm" 5 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" 6 | 7 | npm run husky:pre-commit 8 | -------------------------------------------------------------------------------- /docs/common/Merkle.md: -------------------------------------------------------------------------------- 1 | # Merkle 2 | 3 | *QEDK* 4 | 5 | > Merkle 6 | 7 | Gas optimized verification of proof of inclusion for a leaf in an ordered Merkle tree 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "rules": { 4 | "compiler-version": ["error", "^0.8.0"], 5 | "func-visibility": ["warn", { "ignoreConstructors": true }] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/forge-std"] 2 | path = lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | [submodule "lib/murky"] 5 | path = lib/murky 6 | url = https://github.com/dmfxyz/murky 7 | -------------------------------------------------------------------------------- /docs/lib/WithdrawalQueueLib.md: -------------------------------------------------------------------------------- 1 | # WithdrawalQueueLib 2 | 3 | *Polygon Technology (Daniel Gretzke @gretzke)* 4 | 5 | > Withdrawal Queue Lib 6 | 7 | queue for withdrawals 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /contracts/interfaces/IStateSender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | interface IStateSender { 5 | function syncState(address receiver, bytes calldata data) external; 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interfaces/lib/IValidatorStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | error AmountZero(); 5 | error NotFound(address validator); 6 | error Exists(address validator); 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IAddressList.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | interface IAddressList { 5 | function readAddressList(address account) external view returns (uint256); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interfaces/Errors.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | error Unauthorized(string only); 5 | error StakeRequirement(string src, string msg); 6 | error InvalidSignature(address signer); 7 | -------------------------------------------------------------------------------- /contracts/interfaces/child/IStateReceiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | interface IStateReceiver { 5 | function onStateReceive(uint256 counter, address sender, bytes calldata data) external; 6 | } 7 | -------------------------------------------------------------------------------- /contracts/mocks/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; 5 | 6 | contract MockERC20 is ERC20PresetMinterPauser("TEST", "TEST") {} 7 | -------------------------------------------------------------------------------- /contracts/mocks/MockERC1155.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.19; 3 | 4 | import "@openzeppelin/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol"; 5 | 6 | contract MockERC1155 is ERC1155PresetMinterPauser("lorem") {} 7 | -------------------------------------------------------------------------------- /contracts/mocks/MockERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.19; 3 | 4 | import "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; 5 | 6 | contract MockERC721 is ERC721PresetMinterPauserAutoId("TEST", "TEST", "lorem") {} 7 | -------------------------------------------------------------------------------- /docs/root/staking/StakeManagerStakingData.md: -------------------------------------------------------------------------------- 1 | # StakeManagerStakingData 2 | 3 | 4 | 5 | > StakeManagerStakingData 6 | 7 | Holds all staking related data. Note that this is contract is designed to be included in StakeManager. It is upgradeable. 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage* 5 | gasReporterOutput.json 6 | typechain 7 | typechain-types 8 | .husky 9 | .prettierignore 10 | foundry.toml 11 | forge 12 | forge-cache 13 | out 14 | !/broadcast 15 | /broadcast/* 16 | /broadcast/*/31337/ 17 | slither.db.json 18 | docs/ 19 | lib/ -------------------------------------------------------------------------------- /docs/root/staking/StakeManagerChildData.md: -------------------------------------------------------------------------------- 1 | # StakeManagerChildData 2 | 3 | 4 | 5 | > StakeManagerChildData 6 | 7 | Holds data to allow look-up between child chain manager contract address and child chain id. Note that this is contract is designed to be included in StakeManager. It is upgradeable. 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "outDir": "dist", 8 | "declaration": true 9 | }, 10 | "include": ["./scripts", "./ts", "./test", "./typechain-types"], 11 | "files": ["./hardhat.config.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /docs/lib/ModexpSqrt.md: -------------------------------------------------------------------------------- 1 | # ModexpSqrt 2 | 3 | 4 | 5 | > Compute Square Root by Modular Exponentiation 6 | 7 | Compute $input^{(N + 1) / 4} mod N$ using Addition Chain method. Where N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 and (N + 1) / 4 = 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /script/deployment/rootContractSetConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ProxyAdmin": { 3 | "proxyAdminOwner": "" 4 | }, 5 | 6 | "CheckpointManager": { 7 | "initiator": "" 8 | }, 9 | 10 | "CustomSupernetManager": { 11 | "newStakeManager": "", 12 | "newBls": "", 13 | "newMatic": "", 14 | "newChildValidatorSet": "", 15 | "newRootERC20Predicate": "", 16 | "newDomain": "" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/constants.ts: -------------------------------------------------------------------------------- 1 | /// @notice This bytecode is used to mock and return true with any input 2 | export const alwaysTrueBytecode = "0x600160005260206000F3"; 3 | /// @notice This bytecode is used to mock and return false with any input 4 | export const alwaysFalseBytecode = "0x60206000F3"; 5 | /// @notice This bytecode is used to mock and revert with any input 6 | export const alwaysRevertBytecode = "0x60006000FD"; 7 | -------------------------------------------------------------------------------- /contracts/mocks/StateReceivingContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | contract StateReceivingContract { 5 | uint256 public counter; 6 | 7 | function onStateReceive(uint256 /* id */, address /* sender */, bytes calldata data) external returns (bytes32) { 8 | counter += abi.decode(data, (uint256)); 9 | return bytes32(counter); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /contracts/mocks/MockNativeERC20Transfer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | 6 | contract MockNativeERC20Transfer { 7 | function transferFrom(address token, address receiver, uint256 amount) external { 8 | require(IERC20(token).transferFrom(msg.sender, receiver, amount), "TRANSFER_FAILED"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "singleQuote": false, 6 | "bracketSpacing": true, 7 | "overrides": [ 8 | { 9 | "files": "*.sol", 10 | "options": { 11 | "printWidth": 120, 12 | "tabWidth": 4, 13 | "useTabs": false, 14 | "singleQuote": false, 15 | "bracketSpacing": false 16 | } 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /contracts/mocks/MockSupernetManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "../root/staking/SupernetManager.sol"; 5 | 6 | contract MockSupernetManager is SupernetManager { 7 | function initialize(address stakeManager) public initializer { 8 | __SupernetManager_init(stakeManager); 9 | } 10 | 11 | function _onStake(address validator, uint256 amount) internal override {} 12 | } 13 | -------------------------------------------------------------------------------- /docs/interfaces/IStateSender.md: -------------------------------------------------------------------------------- 1 | # IStateSender 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### syncState 14 | 15 | ```solidity 16 | function syncState(address receiver, bytes data) external nonpayable 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | receiver | address | undefined | 28 | | data | bytes | undefined | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /contracts/interfaces/root/IL2StateReceiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | interface IL2StateReceiver { 5 | /** 6 | * @notice Called by exit helper when state is received from L2 7 | * @param sender Address of the sender on the child chain 8 | * @param data Data sent by the sender 9 | */ 10 | function onL2StateReceive(uint256 id, address sender, bytes calldata data) external; 11 | } 12 | -------------------------------------------------------------------------------- /contracts/interfaces/common/IBN256G2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | interface IBN256G2 { 5 | function ecTwistAdd( 6 | uint256 pt1xx, 7 | uint256 pt1xy, 8 | uint256 pt1yx, 9 | uint256 pt1yy, 10 | uint256 pt2xx, 11 | uint256 pt2xy, 12 | uint256 pt2yx, 13 | uint256 pt2yy 14 | ) external view returns (uint256, uint256, uint256, uint256); 15 | } 16 | -------------------------------------------------------------------------------- /contracts/interfaces/root/IRootValidatorSet.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | interface IRootValidatorSet { 5 | struct Validator { 6 | address _address; 7 | uint256[4] blsKey; 8 | } 9 | 10 | function addValidators(Validator[] calldata newValidators) external; 11 | 12 | function getValidatorBlsKey(uint256 id) external view returns (uint256[4] memory); 13 | 14 | function activeValidatorSetSize() external returns (uint256); 15 | } 16 | -------------------------------------------------------------------------------- /docs/lib/ModexpInverse.md: -------------------------------------------------------------------------------- 1 | # ModexpInverse 2 | 3 | 4 | 5 | > Compute Inverse by Modular Exponentiation 6 | 7 | Compute $input^(N - 2) mod N$ using Addition Chain method. Where N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 and N - 2 = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45 8 | 9 | *the function body is generated with the modified addchain script see https://github.com/kobigurk/addchain/commit/2c37a2ace567a9bdc680b4e929c94aaaa3ec700f* 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/interfaces/child/IStateReceiver.md: -------------------------------------------------------------------------------- 1 | # IStateReceiver 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### onStateReceive 14 | 15 | ```solidity 16 | function onStateReceive(uint256 counter, address sender, bytes data) external nonpayable 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | counter | uint256 | undefined | 28 | | sender | address | undefined | 29 | | data | bytes | undefined | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ts/utils.ts: -------------------------------------------------------------------------------- 1 | import { ethers, BigNumber } from "ethers"; 2 | import { randomBytes, hexlify, hexZeroPad } from "ethers/lib/utils"; 3 | import { FIELD_ORDER } from "./hashToField"; 4 | 5 | export function randHex(n: number): string { 6 | return hexlify(randomBytes(n)); 7 | } 8 | 9 | export function to32Hex(n: BigNumber): string { 10 | return hexZeroPad(n.toHexString(), 32); 11 | } 12 | 13 | export function randFs(): BigNumber { 14 | const r = BigNumber.from(randomBytes(32)); 15 | return r.mod(FIELD_ORDER); 16 | } 17 | -------------------------------------------------------------------------------- /docs/interfaces/IAddressList.md: -------------------------------------------------------------------------------- 1 | # IAddressList 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### readAddressList 14 | 15 | ```solidity 16 | function readAddressList(address account) external view returns (uint256) 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | account | address | undefined | 28 | 29 | #### Returns 30 | 31 | | Name | Type | Description | 32 | |---|---|---| 33 | | _0 | uint256 | undefined | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /contracts/root/staking/README.md: -------------------------------------------------------------------------------- 1 | # Staking 2 | 3 | ##### Contracts for the SupernetManager 4 | 5 | This subdirectory contains contracts making up the Supernet Manager, which serves as a hub for validators to stake on all Supernets tied to a root chain. 6 | 7 | ## CustomSupernetManager 8 | 9 | An implementation of the abstract `SupernetManager` contract. 10 | 11 | ## StakeManager 12 | 13 | Manages validator stake across all Supernets. 14 | 15 | ## SupernetManager 16 | 17 | Abstract contract meant to be customized as a Supernet Manager. 18 | -------------------------------------------------------------------------------- /contracts/child/validator/README.md: -------------------------------------------------------------------------------- 1 | # Validator 2 | 3 | ##### Contracts directly related to validating 4 | 5 | This subdirectory contains contracts directly related to validating on Supernets. 6 | 7 | ## RewardPool 8 | 9 | This contract manages the distribution of assets as rewards for validators validating blocks on the child chain. The contract accounts for rewards due to validators, which validators can withdraw from the contract when distributed. 10 | 11 | ## ValidatorSet 12 | 13 | Manages most direct validator tasks, such as committing epochs or announcing intent to unstake. 14 | -------------------------------------------------------------------------------- /docs/interfaces/root/IL2StateReceiver.md: -------------------------------------------------------------------------------- 1 | # IL2StateReceiver 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### onL2StateReceive 14 | 15 | ```solidity 16 | function onL2StateReceive(uint256 id, address sender, bytes data) external nonpayable 17 | ``` 18 | 19 | Called by exit helper when state is received from L2 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | id | uint256 | undefined | 28 | | sender | address | Address of the sender on the child chain | 29 | | data | bytes | Data sent by the sender | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /script/deployment/common/DeployBLS.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {BLS} from "contracts/common/BLS.sol"; 8 | 9 | abstract contract BLSDeployer is Script { 10 | function deployBLS() internal returns (address contractAddr) { 11 | vm.broadcast(); 12 | BLS bls = new BLS(); 13 | 14 | contractAddr = address(bls); 15 | } 16 | } 17 | 18 | contract DepoyBLS is BLSDeployer { 19 | function run() external returns (address contractAddr) { 20 | return deployBLS(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/interfaces/root/staking/ISupernetManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | /** 5 | @title ISupernetManager 6 | @author Polygon Technology (@gretzke) 7 | @notice Abstract contract for managing supernets 8 | @dev Should be implemented with custom desired functionality 9 | */ 10 | interface ISupernetManager { 11 | /// @notice called when a new child chain is registered 12 | function onInit(uint256 id) external; 13 | 14 | /// @notice called when a validator stakes 15 | function onStake(address validator, uint256 amount) external; 16 | } 17 | -------------------------------------------------------------------------------- /test/forge/utils/Test.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | // 💬 ABOUT 5 | // Custom Test. 6 | 7 | // 🧩 MODULES 8 | import {console} from "forge-std/console.sol"; 9 | import {Assertions} from "./Assertions.sol"; 10 | import {Cheats} from "./Cheats.sol"; 11 | import {stdError} from "forge-std/StdError.sol"; 12 | import {StdUtils} from "forge-std/StdUtils.sol"; 13 | 14 | // 📦 BOILERPLATE 15 | import {TestBase} from "forge-std/Base.sol"; 16 | import {DSTest} from "ds-test/test.sol"; 17 | 18 | // ⭐️ TEST 19 | abstract contract Test is TestBase, DSTest, Assertions, Cheats, StdUtils { 20 | 21 | } 22 | -------------------------------------------------------------------------------- /script/deployment/common/DeployBN256G2.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {BN256G2} from "contracts/common/BN256G2.sol"; 8 | 9 | abstract contract BN256G2Deployer is Script { 10 | function deployBN256G2() internal returns (address contractAddr) { 11 | vm.broadcast(); 12 | BN256G2 bn256G2 = new BN256G2(); 13 | 14 | contractAddr = address(bn256G2); 15 | } 16 | } 17 | 18 | contract DepoyBN256G2 is BN256G2Deployer { 19 | function run() external returns (address contractAddr) { 20 | return deployBN256G2(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /script/deployment/root/DeployStateSender.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {StateSender} from "contracts/root/StateSender.sol"; 8 | 9 | abstract contract StateSenderDeployer is Script { 10 | function deployStateSender() internal returns (address contractAddr) { 11 | vm.broadcast(); 12 | StateSender stateSender = new StateSender(); 13 | 14 | contractAddr = address(stateSender); 15 | } 16 | } 17 | 18 | contract DeployStateSender is StateSenderDeployer { 19 | function run() external returns (address contractAddr) { 20 | return deployStateSender(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeploySystem.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {System} from "contracts/child/System.sol"; 8 | 9 | abstract contract SystemDeployer is Script { 10 | function deploySystem() internal returns (address contractAddr) { 11 | vm.startBroadcast(); 12 | 13 | System system = new System(); 14 | 15 | vm.stopBroadcast(); 16 | 17 | contractAddr = address(system); 18 | } 19 | } 20 | 21 | contract DeploySystem is SystemDeployer { 22 | function run() external returns (address contractAddr) { 23 | return deploySystem(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/forge/root/deployment/DeployStateSender.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Test.sol"; 6 | 7 | import {DeployStateSender} from "script/deployment/root/DeployStateSender.s.sol"; 8 | 9 | import {StateSender} from "contracts/root/StateSender.sol"; 10 | 11 | contract DeployStateSenderTest is Test { 12 | DeployStateSender private deployer; 13 | 14 | StateSender internal stateSender; 15 | 16 | function setUp() public { 17 | deployer = new DeployStateSender(); 18 | 19 | address contractAddr = deployer.run(); 20 | stateSender = StateSender(contractAddr); 21 | } 22 | 23 | function testRun() public { 24 | assertEq(stateSender.counter(), 0); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployL2StateSender.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {L2StateSender} from "contracts/child/L2StateSender.sol"; 8 | 9 | abstract contract L2StateSenderDeployer is Script { 10 | function deployL2StateSender() internal returns (address contractAddr) { 11 | vm.startBroadcast(); 12 | 13 | L2StateSender l2StateSender = new L2StateSender(); 14 | 15 | vm.stopBroadcast(); 16 | 17 | contractAddr = address(l2StateSender); 18 | } 19 | } 20 | 21 | contract DeployL2StateSender is L2StateSenderDeployer { 22 | function run() external returns (address contractAddr) { 23 | return deployL2StateSender(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployStateReceiver.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {StateReceiver} from "contracts/child/StateReceiver.sol"; 8 | 9 | abstract contract StateReceiverDeployer is Script { 10 | function deployStateReceiver() internal returns (address contractAddr) { 11 | vm.startBroadcast(); 12 | 13 | StateReceiver stateReceiver = new StateReceiver(); 14 | 15 | vm.stopBroadcast(); 16 | 17 | contractAddr = address(stateReceiver); 18 | } 19 | } 20 | 21 | contract DeployStateReceiver is StateReceiverDeployer { 22 | function run() external returns (address contractAddr) { 23 | return deployStateReceiver(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/interfaces/child/IChildERC1155Predicate.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "./IChildERC1155.sol"; 5 | import "./IStateReceiver.sol"; 6 | 7 | interface IChildERC1155Predicate is IStateReceiver { 8 | function initialize( 9 | address newL2StateSender, 10 | address newStateReceiver, 11 | address newRootERC721Predicate, 12 | address newChildTokenTemplate 13 | ) external; 14 | 15 | function onStateReceive(uint256 /* id */, address sender, bytes calldata data) external; 16 | 17 | function withdraw(IChildERC1155 childToken, uint256 tokenId, uint256 amount) external; 18 | 19 | function withdrawTo(IChildERC1155 childToken, address receiver, uint256 tokenId, uint256 amount) external; 20 | } 21 | -------------------------------------------------------------------------------- /contracts/interfaces/child/IChildERC20Predicate.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "./IStateReceiver.sol"; 5 | import "./IChildERC20.sol"; 6 | 7 | interface IChildERC20Predicate is IStateReceiver { 8 | function initialize( 9 | address newL2StateSender, 10 | address newStateReceiver, 11 | address newRootERC20Predicate, 12 | address newChildTokenTemplate, 13 | address newNativeTokenRootAddress 14 | ) external; 15 | 16 | function onStateReceive(uint256 /* id */, address sender, bytes calldata data) external; 17 | 18 | function withdraw(IChildERC20 childToken, uint256 amount) external; 19 | 20 | function withdrawTo(IChildERC20 childToken, address receiver, uint256 amount) external; 21 | } 22 | -------------------------------------------------------------------------------- /test/forge/child/ChildERC20Predicate.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@utils/Test.sol"; 5 | 6 | import "contracts/child/ChildERC20.sol"; 7 | import "contracts/child/ChildERC20Predicate.sol"; 8 | import "contracts/interfaces/IStateSender.sol"; 9 | import "contracts/interfaces/child/IChildERC20.sol"; 10 | 11 | contract ChildERC20PredicateTest is Test { 12 | ChildERC20Predicate predicate; 13 | address rootERC20Predicate; 14 | address stateReceiver; 15 | ChildERC20 tokenTemplate; 16 | 17 | address alice; 18 | address bob; 19 | 20 | function setUp() public { 21 | predicate = ChildERC20Predicate(proxify("ChildERC20Predicate.sol", "")); 22 | 23 | alice = makeAddr("Alice"); 24 | bob = makeAddr("Bob"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/interfaces/lib/IWithdrawalQueue.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | /** 5 | * @notice data type for withdrawals 6 | * @param amount the amount to withdraw 7 | * @param epoch the epoch of the withdrawal 8 | */ 9 | struct Withdrawal { 10 | uint256 amount; 11 | uint256 epoch; 12 | } 13 | 14 | /** 15 | * @notice data type for managing the withdrawal queue 16 | * @param head earliest unprocessed index 17 | * (which is also the most recently filled witrhdrawal) 18 | * @param tail index of most recent withdrawal 19 | * (which is also the total number of submitted withdrawals) 20 | * @param withdrawals Withdrawal structs by index 21 | */ 22 | struct WithdrawalQueue { 23 | uint256 head; 24 | uint256 tail; 25 | mapping(uint256 => Withdrawal) withdrawals; 26 | } 27 | -------------------------------------------------------------------------------- /test/forge/utils/Cheats.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | // 💬 ABOUT 5 | // StdCheats and custom cheats. 6 | 7 | // 🧩 MODULES 8 | import {StdCheats} from "forge-std/StdCheats.sol"; 9 | 10 | // 📦 BOILERPLATE 11 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 12 | 13 | // ⭐️ CHEATS 14 | abstract contract Cheats is StdCheats { 15 | address immutable PROXY_ADMIN = makeAddr("PROXY_ADMIN"); 16 | 17 | function proxify(string memory what, bytes memory args) internal returns (address proxyAddr) { 18 | address logicAddr = deployCode(what, args); 19 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(logicAddr, PROXY_ADMIN, ""); 20 | proxyAddr = address(proxy); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/interfaces/lib/IValidatorQueue.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | /** 5 | * @notice data type representing validator in queue 6 | * @param validator the address of the validator 7 | * @param stake the amount staked by the validator 8 | * @param delegation the amount delegated to this validator 9 | */ 10 | struct QueuedValidator { 11 | address validator; 12 | int256 stake; 13 | int256 delegation; 14 | } 15 | 16 | /** 17 | * @notice data type for the management of the queue 18 | * @param indices position of a validator in the queue array 19 | * @param queue array of QueuedValidators 20 | */ 21 | struct ValidatorQueue { 22 | // queue must be first element in struct for the assembly reset 23 | QueuedValidator[] queue; 24 | mapping(address => uint256) indices; 25 | } 26 | -------------------------------------------------------------------------------- /script/deployment/rootTokenContractsConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "common": { 3 | "proxyAdmin": "", 4 | "newStateSender": "", 5 | "newExitHelper": "" 6 | }, 7 | 8 | "RootERC20Predicate": { 9 | "newChildERC20Predicate": "", 10 | "newChildTokenTemplate": "", 11 | "nativeTokenRootAddress": "" 12 | }, 13 | 14 | "ChildMintableERC20Predicate": { 15 | "newChildTokenTemplate": "" 16 | }, 17 | 18 | "RootERC721Predicate": { 19 | "newChildERC721Predicate": "", 20 | "newChildTokenTemplate": "" 21 | }, 22 | 23 | "ChildMintableERC721Predicate": { 24 | "newChildTokenTemplate": "" 25 | }, 26 | 27 | "RootERC1155Predicate": { 28 | "newChildERC1155Predicate": "", 29 | "newChildTokenTemplate": "" 30 | }, 31 | 32 | "ChildMintableERC1155Predicate": { 33 | "newChildTokenTemplate": "" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = 'contracts' 3 | test = 'test/forge' 4 | libs = ['node_modules', 'lib'] 5 | out = 'out' 6 | cache_path = 'forge-cache' 7 | remappings = [ 8 | "@utils=test/forge/utils/" 9 | ] 10 | verbosity = 2 11 | ffi = true 12 | # comment out if you notice any weird behavior 13 | # sparse_mode = true 14 | fs_permissions = [ 15 | { access = "read", path = "script/deployment/sharedRootContractsConfig.json" }, 16 | { access = "read", path = "script/deployment/rootContractSetConfig.json" }, 17 | { access = "read", path = "script/deployment/rootTokenContractsConfig.json" }, 18 | { access = "read", path = "out/" } 19 | ] 20 | 21 | # do not use for computationally expensive tests 22 | [profile.intense.fuzz] 23 | runs = 10000 24 | max_test_rejects = 999999 25 | 26 | # See more config options https://book.getfoundry.sh/reference/config.html 27 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: false, 4 | es2021: true, 5 | mocha: true, 6 | node: true, 7 | }, 8 | plugins: ["@typescript-eslint", "prettier"], 9 | extends: ["standard", "plugin:node/recommended", "plugin:prettier/recommended"], 10 | parser: "@typescript-eslint/parser", 11 | parserOptions: { 12 | ecmaVersion: 12, 13 | }, 14 | rules: { 15 | "node/no-unsupported-features/es-syntax": ["error", { ignores: ["modules"] }], 16 | "prettier/prettier": ["error", {}], 17 | "arrow-body-style": "off", 18 | "prefer-arrow-callback": "off", 19 | "node/no-missing-import": [ 20 | "error", 21 | { 22 | allowModules: [], 23 | resolvePaths: ["node_modules", "./test"], 24 | tryExtensions: [".ts", ".js"], 25 | }, 26 | ], 27 | "no-unused-expressions": "off", 28 | }, 29 | }; 30 | -------------------------------------------------------------------------------- /contracts/interfaces/child/IChildERC721Predicate.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "./IChildERC721.sol"; 5 | import "./IStateReceiver.sol"; 6 | 7 | interface IChildERC721Predicate is IStateReceiver { 8 | function initialize( 9 | address newL2StateSender, 10 | address newStateReceiver, 11 | address newRootERC721Predicate, 12 | address newChildTokenTemplate 13 | ) external; 14 | 15 | function onStateReceive(uint256 /* id */, address sender, bytes calldata data) external; 16 | 17 | function withdraw(IChildERC721 childToken, uint256 tokenId) external; 18 | 19 | function withdrawTo(IChildERC721 childToken, address receiver, uint256 tokenId) external; 20 | 21 | function withdrawBatch(IChildERC721 childToken, address[] calldata receivers, uint256[] calldata tokenIds) external; 22 | } 23 | -------------------------------------------------------------------------------- /contracts/lib/SafeMathInt.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | library SafeMathInt { 5 | /** 6 | * @notice converts an int256 to uint256 7 | * @param a int256 to convert 8 | * @return uint256 of the input 9 | */ 10 | // slither-disable-next-line dead-code 11 | function toUint256Safe(int256 a) internal pure returns (uint256) { 12 | assert(a >= 0); 13 | return uint256(a); 14 | } 15 | } 16 | 17 | library SafeMathUint { 18 | /** 19 | * @notice converts a uint256 to int256 20 | * @param a the uint256 to convert 21 | * @return int256 of the input 22 | */ 23 | // slither-disable-next-line dead-code 24 | function toInt256Safe(uint256 a) internal pure returns (int256) { 25 | int256 b = int256(a); 26 | assert(b >= 0); 27 | return b; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /docs/interfaces/root/staking/ISupernetManager.md: -------------------------------------------------------------------------------- 1 | # ISupernetManager 2 | 3 | *Polygon Technology (@gretzke)* 4 | 5 | > ISupernetManager 6 | 7 | Abstract contract for managing supernets 8 | 9 | *Should be implemented with custom desired functionality* 10 | 11 | ## Methods 12 | 13 | ### onInit 14 | 15 | ```solidity 16 | function onInit(uint256 id) external nonpayable 17 | ``` 18 | 19 | called when a new child chain is registered 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | id | uint256 | undefined | 28 | 29 | ### onStake 30 | 31 | ```solidity 32 | function onStake(address validator, uint256 amount) external nonpayable 33 | ``` 34 | 35 | called when a validator stakes 36 | 37 | 38 | 39 | #### Parameters 40 | 41 | | Name | Type | Description | 42 | |---|---|---| 43 | | validator | address | undefined | 44 | | amount | uint256 | undefined | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /test/forge/root/generateMsgSupernetManager.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | import * as mcl from "../../../ts/mcl"; 3 | const signerAddress = process.argv[2]; 4 | const contractAddress = process.argv[3]; 5 | 6 | const DOMAIN = ethers.utils.arrayify(ethers.utils.solidityKeccak256(["string"], ["CUSTOM_SUPERNET_MANAGER"])); 7 | const CHAIN_ID = 31337; 8 | 9 | async function generateRegistrationSignature(signerAddress: string, contractAddress: string) { 10 | await mcl.init(); 11 | const { pubkey, secret } = mcl.newKeyPair(); 12 | const parsedPubkey = mcl.g2ToHex(pubkey); 13 | const { signature } = mcl.signSupernetMessage(DOMAIN, CHAIN_ID, signerAddress, contractAddress, secret); 14 | 15 | const parsedSignature = mcl.g1ToHex(signature); 16 | 17 | const output = ethers.utils.defaultAbiCoder.encode(["uint256[2]", "uint256[4]"], [parsedSignature, parsedPubkey]); 18 | 19 | console.log(output); 20 | } 21 | 22 | generateRegistrationSignature(signerAddress, contractAddress); 23 | -------------------------------------------------------------------------------- /docs/interfaces/common/IBN256G2.md: -------------------------------------------------------------------------------- 1 | # IBN256G2 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### ecTwistAdd 14 | 15 | ```solidity 16 | function ecTwistAdd(uint256 pt1xx, uint256 pt1xy, uint256 pt1yx, uint256 pt1yy, uint256 pt2xx, uint256 pt2xy, uint256 pt2yx, uint256 pt2yy) external view returns (uint256, uint256, uint256, uint256) 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | pt1xx | uint256 | undefined | 28 | | pt1xy | uint256 | undefined | 29 | | pt1yx | uint256 | undefined | 30 | | pt1yy | uint256 | undefined | 31 | | pt2xx | uint256 | undefined | 32 | | pt2xy | uint256 | undefined | 33 | | pt2yx | uint256 | undefined | 34 | | pt2yy | uint256 | undefined | 35 | 36 | #### Returns 37 | 38 | | Name | Type | Description | 39 | |---|---|---| 40 | | _0 | uint256 | undefined | 41 | | _1 | uint256 | undefined | 42 | | _2 | uint256 | undefined | 43 | | _3 | uint256 | undefined | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /test/lib/AccessList.test.ts: -------------------------------------------------------------------------------- 1 | import { setCode, impersonateAccount, setBalance } from "@nomicfoundation/hardhat-network-helpers"; 2 | import { expect } from "chai"; 3 | import * as hre from "hardhat"; 4 | import { ethers, network } from "hardhat"; 5 | import { AccessList, Access } from "../../typechain-types"; 6 | import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; 7 | import { alwaysTrueBytecode } from "../constants"; 8 | 9 | describe("AccessList", () => { 10 | let accessList: AccessList, accounts: SignerWithAddress[]; 11 | 12 | before(async () => { 13 | await hre.network.provider.send("hardhat_reset"); 14 | accounts = await ethers.getSigners(); 15 | 16 | await setCode("0x0200000000000000000000000000000000000004", alwaysTrueBytecode); 17 | await setCode("0x0300000000000000000000000000000000000004", alwaysTrueBytecode); 18 | 19 | const AccessList = await ethers.getContractFactory("AccessList"); 20 | accessList = await AccessList.deploy(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Polygon Technology 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /docs/interfaces/root/IExitHelper.md: -------------------------------------------------------------------------------- 1 | # IExitHelper 2 | 3 | *@QEDK (Polygon Technology)* 4 | 5 | > ExitHelper 6 | 7 | Helper contract to process exits from stored event roots in CheckpointManager 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### batchExit 14 | 15 | ```solidity 16 | function batchExit(IExitHelper.BatchExitInput[] inputs) external nonpayable 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | inputs | IExitHelper.BatchExitInput[] | undefined | 28 | 29 | ### exit 30 | 31 | ```solidity 32 | function exit(uint256 blockNumber, uint256 leafIndex, bytes unhashedLeaf, bytes32[] proof) external nonpayable 33 | ``` 34 | 35 | Perform an exit for one event 36 | 37 | 38 | 39 | #### Parameters 40 | 41 | | Name | Type | Description | 42 | |---|---|---| 43 | | blockNumber | uint256 | Block number of the exit event on L2 | 44 | | leafIndex | uint256 | Index of the leaf in the exit event Merkle tree | 45 | | unhashedLeaf | bytes | ABI-encoded exit event leaf | 46 | | proof | bytes32[] | Proof of the event inclusion in the tree | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /test/forge/child/ChildERC20.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@utils/Test.sol"; 5 | 6 | import {ChildERC20} from "contracts/child/ChildERC20.sol"; 7 | import {ChildERC20Predicate} from "contracts/child/ChildERC20Predicate.sol"; 8 | 9 | contract ChildERC20Test is Test { 10 | ChildERC20 childERC20; 11 | ChildERC20Predicate predicate; 12 | address rootTokenAddress; 13 | 14 | address alice; 15 | address bob; 16 | 17 | string name = "TEST"; 18 | uint8 decimals = 18; 19 | 20 | function setUp() public { 21 | childERC20 = ChildERC20(proxify("ChildERC20.sol", "")); 22 | predicate = ChildERC20Predicate(proxify("ChildERC20Predicate.sol", "")); 23 | 24 | alice = makeAddr("Alice"); 25 | bob = makeAddr("Bob"); 26 | } 27 | 28 | function testInitialize() public {} 29 | 30 | function testDecimals() public {} 31 | 32 | function testPredicate() public {} 33 | 34 | function testRootToken() public {} 35 | 36 | function testMint() public {} 37 | 38 | function testBurn() public {} 39 | 40 | function test_msgSender() public {} 41 | } 42 | -------------------------------------------------------------------------------- /docs/interfaces/root/IRootValidatorSet.md: -------------------------------------------------------------------------------- 1 | # IRootValidatorSet 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### activeValidatorSetSize 14 | 15 | ```solidity 16 | function activeValidatorSetSize() external nonpayable returns (uint256) 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | 24 | #### Returns 25 | 26 | | Name | Type | Description | 27 | |---|---|---| 28 | | _0 | uint256 | undefined | 29 | 30 | ### addValidators 31 | 32 | ```solidity 33 | function addValidators(IRootValidatorSet.Validator[] newValidators) external nonpayable 34 | ``` 35 | 36 | 37 | 38 | 39 | 40 | #### Parameters 41 | 42 | | Name | Type | Description | 43 | |---|---|---| 44 | | newValidators | IRootValidatorSet.Validator[] | undefined | 45 | 46 | ### getValidatorBlsKey 47 | 48 | ```solidity 49 | function getValidatorBlsKey(uint256 id) external view returns (uint256[4]) 50 | ``` 51 | 52 | 53 | 54 | 55 | 56 | #### Parameters 57 | 58 | | Name | Type | Description | 59 | |---|---|---| 60 | | id | uint256 | undefined | 61 | 62 | #### Returns 63 | 64 | | Name | Type | Description | 65 | |---|---|---| 66 | | _0 | uint256[4] | undefined | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /docs/lib/EIP712Upgradeable.md: -------------------------------------------------------------------------------- 1 | # EIP712Upgradeable 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | *https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in their contracts using a combination of `abi.encode` and `keccak256`. This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA ({_hashTypedDataV4}). The implementation of the domain separator was designed to be as efficient as possible while still properly updating the chain id to protect against replay attacks on an eventual fork of the chain. NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. _Available since v3.4._* 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /contracts/interfaces/root/IChildMintableERC20Predicate.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "../child/IChildERC20.sol"; 5 | import "./IL2StateReceiver.sol"; 6 | 7 | interface IChildMintableERC20Predicate is IL2StateReceiver { 8 | event MintableERC20Deposit( 9 | address indexed rootToken, 10 | address indexed childToken, 11 | address sender, 12 | address indexed receiver, 13 | uint256 amount 14 | ); 15 | event MintableERC20Withdraw( 16 | address indexed rootToken, 17 | address indexed childToken, 18 | address sender, 19 | address indexed receiver, 20 | uint256 amount 21 | ); 22 | event MintableTokenMapped(address indexed rootToken, address indexed childToken); 23 | 24 | function initialize( 25 | address newL2StateSender, 26 | address newStateReceiver, 27 | address newRootERC20Predicate, 28 | address newChildTokenTemplate 29 | ) external; 30 | 31 | function withdraw(IChildERC20 childToken, uint256 amount) external; 32 | 33 | function withdrawTo(IChildERC20 childToken, address receiver, uint256 amount) external; 34 | } 35 | -------------------------------------------------------------------------------- /contracts/interfaces/root/IExitHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | /** 5 | * @title ExitHelper 6 | * @author @QEDK (Polygon Technology) 7 | * @notice Helper contract to process exits from stored event roots in CheckpointManager 8 | */ 9 | interface IExitHelper { 10 | struct BatchExitInput { 11 | uint256 blockNumber; 12 | uint256 leafIndex; 13 | bytes unhashedLeaf; 14 | bytes32[] proof; 15 | } 16 | 17 | /** 18 | * @notice Perform an exit for one event 19 | * @param blockNumber Block number of the exit event on L2 20 | * @param leafIndex Index of the leaf in the exit event Merkle tree 21 | * @param unhashedLeaf ABI-encoded exit event leaf 22 | * @param proof Proof of the event inclusion in the tree 23 | */ 24 | function exit( 25 | uint256 blockNumber, 26 | uint256 leafIndex, 27 | bytes calldata unhashedLeaf, 28 | bytes32[] calldata proof 29 | ) external; 30 | 31 | /** 32 | * @notice Perform a batch exit for multiple events 33 | * @param inputs Batch exit inputs for multiple event leaves 34 | */ 35 | function batchExit(BatchExitInput[] calldata inputs) external; 36 | } 37 | -------------------------------------------------------------------------------- /contracts/root/StateSender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "../interfaces/IStateSender.sol"; 5 | 6 | contract StateSender is IStateSender { 7 | uint256 public constant MAX_LENGTH = 2048; 8 | uint256 public counter; 9 | 10 | event StateSynced(uint256 indexed id, address indexed sender, address indexed receiver, bytes data); 11 | 12 | /** 13 | * 14 | * @notice Generates sync state event based on receiver and data. 15 | * Anyone can call this method to emit an event. Receiver on Polygon should add check based on sender. 16 | * 17 | * @param receiver Receiver address on Polygon chain 18 | * @param data Data to send on Polygon chain 19 | * 20 | */ 21 | function syncState(address receiver, bytes calldata data) external { 22 | // check receiver 23 | require(receiver != address(0), "INVALID_RECEIVER"); 24 | // check data length 25 | require(data.length <= MAX_LENGTH, "EXCEEDS_MAX_LENGTH"); 26 | 27 | // State sync id will start with 1 28 | emit StateSynced(++counter, msg.sender, receiver, data); 29 | } 30 | 31 | // slither-disable-next-line unused-state,naming-convention 32 | uint256[50] private __gap; 33 | } 34 | -------------------------------------------------------------------------------- /test/forge/child/ChildERC721.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@utils/Test.sol"; 5 | 6 | import {ChildERC721} from "contracts/child/ChildERC721.sol"; 7 | import {ChildERC721Predicate} from "contracts/child/ChildERC721Predicate.sol"; 8 | 9 | contract ChildERC721Test is Test { 10 | ChildERC721 childERC721; 11 | ChildERC721Predicate predicate; 12 | address rootTokenAddress; 13 | 14 | address alice; 15 | address bob; 16 | 17 | string name = "TEST"; 18 | string URI = "lorem"; 19 | 20 | function setUp() public { 21 | childERC721 = ChildERC721(proxify("ChildERC721.sol", "")); 22 | predicate = ChildERC721Predicate(proxify("ChildERC721Predicate.sol", "")); 23 | 24 | alice = makeAddr("Alice"); 25 | bob = makeAddr("Bob"); 26 | } 27 | 28 | function testInitialize() public {} 29 | 30 | function testDecimals() public {} 31 | 32 | function testPredicate() public {} 33 | 34 | function testRootToken() public {} 35 | 36 | function testMint() public {} 37 | 38 | function testMintBatch() public {} 39 | 40 | function testBurn() public {} 41 | 42 | function testBurnBatch() public {} 43 | 44 | function test_msgSender() public {} 45 | } 46 | -------------------------------------------------------------------------------- /contracts/interfaces/child/validator/IRewardPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "./IValidatorSet.sol"; 6 | 7 | struct Uptime { 8 | address validator; 9 | uint256 signedBlocks; 10 | } 11 | 12 | /** 13 | @title IRewardPool 14 | @author Polygon Technology (@gretzke) 15 | @notice Distributes rewards to validators for committed epochs 16 | */ 17 | interface IRewardPool { 18 | event RewardDistributed(uint256 indexed epochId, uint256 totalReward); 19 | 20 | /// @notice distributes reward for the given epoch 21 | /// @dev transfers funds from sender to this contract 22 | /// @param uptime uptime data for every validator 23 | function distributeRewardFor(uint256 epochId, Uptime[] calldata uptime) external; 24 | 25 | /// @notice withdraws pending rewards for the sender (validator) 26 | function withdrawReward() external; 27 | 28 | /// @notice returns the total reward paid for the given epoch 29 | function paidRewardPerEpoch(uint256 epochId) external view returns (uint256); 30 | 31 | /// @notice returns the pending reward for the given account 32 | function pendingRewards(address account) external view returns (uint256); 33 | } 34 | -------------------------------------------------------------------------------- /test/forge/child/ChildERC1155.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@utils/Test.sol"; 5 | 6 | import {ChildERC1155} from "contracts/child/ChildERC1155.sol"; 7 | import {ChildERC1155Predicate} from "contracts/child/ChildERC1155Predicate.sol"; 8 | 9 | contract ChildERC1155Test is Test { 10 | ChildERC1155 childERC1155; 11 | ChildERC1155Predicate predicate; 12 | address rootTokenAddress; 13 | 14 | address alice; 15 | address bob; 16 | 17 | string URI = "lorem"; 18 | 19 | function setUp() public { 20 | childERC1155 = ChildERC1155(proxify("ChildERC1155.sol", "")); 21 | predicate = ChildERC1155Predicate(proxify("ChildERC1155Predicate.sol", "")); 22 | 23 | alice = makeAddr("Alice"); 24 | bob = makeAddr("Bob"); 25 | } 26 | 27 | function testInitialize() public {} 28 | 29 | function testDecimals() public {} 30 | 31 | function testPredicate() public {} 32 | 33 | function testRootToken() public {} 34 | 35 | function testMint() public {} 36 | 37 | function testMintBatch() public {} 38 | 39 | function testMintBatch2() public {} 40 | 41 | function testBurn() public {} 42 | 43 | function testBurnBatch() public {} 44 | 45 | function test_msgSender() public {} 46 | } 47 | -------------------------------------------------------------------------------- /docs/root/staking/SupernetManager.md: -------------------------------------------------------------------------------- 1 | # SupernetManager 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### id 14 | 15 | ```solidity 16 | function id() external view returns (uint256) 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | 24 | #### Returns 25 | 26 | | Name | Type | Description | 27 | |---|---|---| 28 | | _0 | uint256 | undefined | 29 | 30 | ### onInit 31 | 32 | ```solidity 33 | function onInit(uint256 id_) external nonpayable 34 | ``` 35 | 36 | 37 | 38 | 39 | 40 | #### Parameters 41 | 42 | | Name | Type | Description | 43 | |---|---|---| 44 | | id_ | uint256 | undefined | 45 | 46 | ### onStake 47 | 48 | ```solidity 49 | function onStake(address validator, uint256 amount) external nonpayable 50 | ``` 51 | 52 | called when a validator stakes 53 | 54 | 55 | 56 | #### Parameters 57 | 58 | | Name | Type | Description | 59 | |---|---|---| 60 | | validator | address | undefined | 61 | | amount | uint256 | undefined | 62 | 63 | 64 | 65 | ## Events 66 | 67 | ### Initialized 68 | 69 | ```solidity 70 | event Initialized(uint8 version) 71 | ``` 72 | 73 | 74 | 75 | *Triggered when the contract has been initialized or reinitialized.* 76 | 77 | #### Parameters 78 | 79 | | Name | Type | Description | 80 | |---|---|---| 81 | | version | uint8 | undefined | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # .example.env 2 | 3 | # This file is designed to hold secrets like API and private keys without exposing them. 4 | # Using the project locally without them is possible, but values will be needed here for 5 | # deployment and other actions on public networks and testnets. 6 | 7 | # In order to use this file, copy it and rename it .env 8 | 9 | # Used to signal the gas reporter 10 | # (this is done so that when the tests run on CI where there is no .env, the gas reporter 11 | # won't run) 12 | REPORT_GAS=true 13 | 14 | # A private key is necessary for deploying and/or transacting on public networks 15 | PRIVATE_KEY= 16 | 17 | # The Hardhat config is configured to recognize 4 chains: a production root/child, and a 18 | # test root/child. To run on any of them, put a URL to an RPC in the proper field. For 19 | # example, if you are using Alchemy and need to fork Ethereum mainnet as the root chain, 20 | # you would put the complete URL (including API key) in the ROOT_RPC. 21 | 22 | # If you are running a local node, use a URL to localhost, for example: 23 | # http://localhost:8545 24 | ROOT_RPC= 25 | ROOT_TEST_RPC= 26 | CHILD_RPC= 27 | CHILD_TEST_RPC= 28 | 29 | # An Etherscan API key is needed for verifying contracts on Ethereum (testnets/mainnet), 30 | # while a Polygonscan API key is needed for Polygon's chains. 31 | ETHERSCAN_API_KEY= 32 | POLYGONSCAN_API_KEY= -------------------------------------------------------------------------------- /contracts/child/System.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "../interfaces/Errors.sol"; 5 | 6 | contract System { 7 | // pre-compiled contracts 8 | // slither-disable too-many-digits 9 | address public constant NATIVE_TRANSFER_PRECOMPILE = 0x0000000000000000000000000000000000002020; 10 | address public constant VALIDATOR_PKCHECK_PRECOMPILE = 0x0000000000000000000000000000000000002030; 11 | address public constant ALLOWLIST_PRECOMPILE = 0x0200000000000000000000000000000000000004; 12 | address public constant BLOCKLIST_PRECOMPILE = 0x0300000000000000000000000000000000000004; 13 | 14 | // internal addrs 15 | address public constant SYSTEM = 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE; 16 | 17 | // pre-compiled gas consumption 18 | uint256 public constant NATIVE_TRANSFER_PRECOMPILE_GAS = 21000; 19 | uint256 public constant VALIDATOR_PKCHECK_PRECOMPILE_GAS = 150000; 20 | uint256 public constant READ_ADDRESSLIST_GAS = 5000; 21 | 22 | // genesis contracts 23 | address public constant NATIVE_TOKEN_CONTRACT = 0x0000000000000000000000000000000000001010; 24 | 25 | modifier onlySystemCall() { 26 | if (msg.sender != SYSTEM) revert Unauthorized("SYSTEMCALL"); 27 | _; 28 | } 29 | 30 | // slither-disable-next-line unused-state,naming-convention 31 | uint256[50] private __gap; 32 | } 33 | -------------------------------------------------------------------------------- /script/deployment/root/staking/DeployStakeManager.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {StakeManager} from "contracts/root/staking/StakeManager.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract StakeManagerDeployer is Script { 11 | function deployStakeManager( 12 | address proxyAdmin, 13 | address newStakingToken 14 | ) internal returns (address logicAddr, address proxyAddr) { 15 | bytes memory initData = abi.encodeCall(StakeManager.initialize, (newStakingToken)); 16 | 17 | vm.startBroadcast(); 18 | 19 | StakeManager stakeManager = new StakeManager(); 20 | 21 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 22 | address(stakeManager), 23 | proxyAdmin, 24 | initData 25 | ); 26 | 27 | vm.stopBroadcast(); 28 | 29 | logicAddr = address(stakeManager); 30 | proxyAddr = address(proxy); 31 | } 32 | } 33 | 34 | contract DeployStakeManager is StakeManagerDeployer { 35 | function run(address proxyAdmin, address newStakingToken) external returns (address logicAddr, address proxyAddr) { 36 | return deployStakeManager(proxyAdmin, newStakingToken); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /contracts/child/L2StateSender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "../interfaces/IStateSender.sol"; 5 | 6 | /** 7 | @title L2StateSender 8 | @author Polygon Technology (@QEDK) 9 | @notice Arbitrary message passing contract from L2 -> L1 10 | @dev There is no transaction execution on L1, only a commitment of the emitted events are stored 11 | */ 12 | contract L2StateSender is IStateSender { 13 | uint256 public constant MAX_LENGTH = 2048; 14 | uint256 public counter; 15 | 16 | event L2StateSynced(uint256 indexed id, address indexed sender, address indexed receiver, bytes data); 17 | 18 | /** 19 | * @notice Emits an event which is indexed by v3 validators and submitted as a commitment on L1 20 | * allowing for lazy execution 21 | * @param receiver Address of the message recipient on L1 22 | * @param data Data to use in message call to recipient 23 | */ 24 | function syncState(address receiver, bytes calldata data) external { 25 | // check receiver 26 | require(receiver != address(0), "INVALID_RECEIVER"); 27 | // check data length 28 | require(data.length <= MAX_LENGTH, "EXCEEDS_MAX_LENGTH"); 29 | 30 | emit L2StateSynced(++counter, msg.sender, receiver, data); 31 | } 32 | 33 | // slither-disable-next-line unused-state,naming-convention 34 | uint256[50] private __gap; 35 | } 36 | -------------------------------------------------------------------------------- /contracts/root/README.md: -------------------------------------------------------------------------------- 1 | # Root 2 | 3 | ##### Contracts providing functionality on the root chain 4 | 5 | This directory contains contracts meant for usage on the root chain. A brief overview of what the contracts do and how they work is provided here. For more granular documentation, there is extensive natspec on the contracts, along with markdown docs automatically generated from the natspec in the [`docs/`](../../docs/) directory at the project root. 6 | 7 | ## Checkpoint Manager 8 | 9 | Used for receiving messages on the root chain. Batches of blocks and an event root are received from validators, then the message payloads are executed. This is different than state sender since this receives from L2, whereas state sender _sends_ to L2. This requires a separate contract since the user is expected to execute after the state is received, unlike on child. 10 | 11 | ## State Sender 12 | 13 | Sends messages to child. Messages are indexed by validators from root and then signed. Once they have enough signatures they can be committed on `StateReceiver` on child. 14 | 15 | Unlike the current implementation of child, sending and receiving messages is split into two contracts on root. 16 | 17 | ## `staking/` 18 | 19 | There is an additional subdirectory with contracts directly relating to Supernet managers, or contracts meant as a hub on root for all child chains. A separate README in that directory describes the contracts there. 20 | -------------------------------------------------------------------------------- /script/deployment/DeploySharedRootContracts.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; 8 | 9 | import "script/deployment/common/DeployBLS.s.sol"; 10 | import "script/deployment/common/DeployBN256G2.s.sol"; 11 | import "script/deployment/root/staking/DeployStakeManager.s.sol"; 12 | 13 | contract DeploySharedRootContracts is BLSDeployer, BN256G2Deployer, StakeManagerDeployer { 14 | using stdJson for string; 15 | 16 | function run() 17 | external 18 | returns (address proxyAdmin, address bls, address bn256G2, address stakeManagerLogic, address stakeManagerProxy) 19 | { 20 | string memory config = vm.readFile("script/deployment/sharedRootContractsConfig.json"); 21 | 22 | vm.startBroadcast(); 23 | 24 | ProxyAdmin _proxyAdmin = new ProxyAdmin(); 25 | _proxyAdmin.transferOwnership(config.readAddress('["ProxyAdmin"].proxyAdminOwner')); 26 | 27 | vm.stopBroadcast(); 28 | 29 | proxyAdmin = address(_proxyAdmin); 30 | 31 | bls = deployBLS(); 32 | 33 | bn256G2 = deployBN256G2(); 34 | 35 | (stakeManagerLogic, stakeManagerProxy) = deployStakeManager( 36 | proxyAdmin, 37 | config.readAddress('["StakeManager"].newStakingToken') 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /script/deployment/root/DeployExitHelper.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ExitHelper} from "contracts/root/ExitHelper.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | import {ICheckpointManager} from "contracts/interfaces/root/ICheckpointManager.sol"; 11 | 12 | abstract contract ExitHelperDeployer is Script { 13 | function deployExitHelper( 14 | address proxyAdmin, 15 | ICheckpointManager checkpointManager 16 | ) internal returns (address logicAddr, address proxyAddr) { 17 | bytes memory initData = abi.encodeCall(ExitHelper.initialize, (checkpointManager)); 18 | 19 | vm.startBroadcast(); 20 | 21 | ExitHelper exitHelper = new ExitHelper(); 22 | 23 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(exitHelper), proxyAdmin, initData); 24 | 25 | vm.stopBroadcast(); 26 | 27 | logicAddr = address(exitHelper); 28 | proxyAddr = address(proxy); 29 | } 30 | } 31 | 32 | contract DeployExitHelper is ExitHelperDeployer { 33 | function run( 34 | address proxyAdmin, 35 | ICheckpointManager checkpointManager 36 | ) external returns (address logicAddr, address proxyAddr) { 37 | return deployExitHelper(proxyAdmin, checkpointManager); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/root/staking/SupernetManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; 5 | import "../../interfaces/root/staking/IStakeManager.sol"; 6 | import "../../interfaces/root/staking/ISupernetManager.sol"; 7 | 8 | abstract contract SupernetManager is ISupernetManager, Initializable { 9 | // slither-disable-next-line naming-convention 10 | IStakeManager internal _stakeManager; 11 | uint256 public id; 12 | 13 | modifier onlyStakeManager() { 14 | require(msg.sender == address(_stakeManager), "SupernetManager: ONLY_STAKE_MANAGER"); 15 | _; 16 | } 17 | 18 | // slither-disable-next-line naming-convention 19 | function __SupernetManager_init(address newStakeManager) internal onlyInitializing { 20 | _stakeManager = IStakeManager(newStakeManager); 21 | } 22 | 23 | function onInit(uint256 id_) external onlyStakeManager { 24 | require(id == 0, "SupernetManager: ID_ALREADY_SET"); 25 | // slither-disable-next-line events-maths 26 | id = id_; 27 | } 28 | 29 | function onStake(address validator, uint256 amount) external onlyStakeManager { 30 | _onStake(validator, amount); 31 | } 32 | 33 | function _onStake(address validator, uint256 amount) internal virtual; 34 | 35 | // slither-disable-next-line unused-state,naming-convention 36 | uint256[50] private __gap; 37 | } 38 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployChildERC1155.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildERC1155} from "contracts/child/ChildERC1155.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildERC1155Deployer is Script { 11 | function deployChildERC1155( 12 | address proxyAdmin, 13 | address rootToken_, 14 | string memory uri_ 15 | ) internal returns (address logicAddr, address proxyAddr) { 16 | bytes memory initData = abi.encodeCall(ChildERC1155.initialize, (rootToken_, uri_)); 17 | 18 | vm.startBroadcast(); 19 | 20 | ChildERC1155 childERC1155 = new ChildERC1155(); 21 | 22 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 23 | address(childERC1155), 24 | proxyAdmin, 25 | initData 26 | ); 27 | 28 | vm.stopBroadcast(); 29 | 30 | logicAddr = address(childERC1155); 31 | proxyAddr = address(proxy); 32 | } 33 | } 34 | 35 | contract DeployChildERC1155 is ChildERC1155Deployer { 36 | function run( 37 | address proxyAdmin, 38 | address rootToken_, 39 | string memory uri_ 40 | ) external returns (address logicAddr, address proxyAddr) { 41 | return deployChildERC1155(proxyAdmin, rootToken_, uri_); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployChildERC721.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildERC721} from "contracts/child/ChildERC721.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildERC721Deployer is Script { 11 | function deployChildERC721( 12 | address proxyAdmin, 13 | address rootToken_, 14 | string memory name_, 15 | string memory symbol_ 16 | ) internal returns (address logicAddr, address proxyAddr) { 17 | bytes memory initData = abi.encodeCall(ChildERC721.initialize, (rootToken_, name_, symbol_)); 18 | 19 | vm.startBroadcast(); 20 | 21 | ChildERC721 childERC721 = new ChildERC721(); 22 | 23 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(childERC721), proxyAdmin, initData); 24 | 25 | vm.stopBroadcast(); 26 | 27 | logicAddr = address(childERC721); 28 | proxyAddr = address(proxy); 29 | } 30 | } 31 | 32 | contract DeployChildERC721 is ChildERC721Deployer { 33 | function run( 34 | address proxyAdmin, 35 | address rootToken_, 36 | string memory name_, 37 | string memory symbol_ 38 | ) external returns (address logicAddr, address proxyAddr) { 39 | return deployChildERC721(proxyAdmin, rootToken_, name_, symbol_); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /contracts/child/ChildERC721PredicateAccessList.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import {ChildERC721Predicate} from "./ChildERC721Predicate.sol"; 5 | import {AccessList} from "../lib/AccessList.sol"; 6 | 7 | /** 8 | @title ChildERC721PredicateAccessList 9 | @author Polygon Technology (@QEDK) 10 | @notice Enables ERC721 token deposits and withdrawals (only from allowlisted address, and not from blocklisted addresses) across an arbitrary root chain and child chain 11 | */ 12 | // solhint-disable reason-string 13 | contract ChildERC721PredicateAccessList is AccessList, ChildERC721Predicate { 14 | constructor() { 15 | _disableInitializers(); 16 | } 17 | 18 | function initialize( 19 | address newL2StateSender, 20 | address newStateReceiver, 21 | address newRootERC721Predicate, 22 | address newChildTokenTemplate, 23 | bool newUseAllowList, 24 | bool newUseBlockList, 25 | address newOwner 26 | ) public virtual onlySystemCall initializer { 27 | _initialize(newL2StateSender, newStateReceiver, newRootERC721Predicate, newChildTokenTemplate); 28 | _initializeAccessList(newUseAllowList, newUseBlockList); 29 | _transferOwnership(newOwner); 30 | } 31 | 32 | function _beforeTokenWithdraw() internal virtual override { 33 | _checkAccessList(); 34 | } 35 | 36 | // slither-disable-next-line unused-state,naming-convention 37 | uint256[50] private __gap; 38 | } 39 | -------------------------------------------------------------------------------- /contracts/child/ChildERC1155PredicateAccessList.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import {ChildERC1155Predicate} from "./ChildERC1155Predicate.sol"; 5 | import {AccessList} from "../lib/AccessList.sol"; 6 | 7 | /** 8 | @title ChildERC1155PredicateAccessList 9 | @author Polygon Technology (@QEDK) 10 | @notice Enables ERC1155 token deposits and withdrawals (only from allowlisted address, and not from blocklisted addresses) across an arbitrary root chain and child chain 11 | */ 12 | // solhint-disable reason-string 13 | contract ChildERC1155PredicateAccessList is AccessList, ChildERC1155Predicate { 14 | constructor() { 15 | _disableInitializers(); 16 | } 17 | 18 | function initialize( 19 | address newL2StateSender, 20 | address newStateReceiver, 21 | address newRootERC1155Predicate, 22 | address newChildTokenTemplate, 23 | bool newUseAllowList, 24 | bool newUseBlockList, 25 | address newOwner 26 | ) public virtual onlySystemCall initializer { 27 | _initialize(newL2StateSender, newStateReceiver, newRootERC1155Predicate, newChildTokenTemplate); 28 | _initializeAccessList(newUseAllowList, newUseBlockList); 29 | _transferOwnership(newOwner); 30 | } 31 | 32 | function _beforeTokenWithdraw() internal virtual override { 33 | _checkAccessList(); 34 | } 35 | 36 | // slither-disable-next-line unused-state,naming-convention 37 | uint256[50] private __gap; 38 | } 39 | -------------------------------------------------------------------------------- /test/forge/libs/SafeMathInt.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@utils/Test.sol"; 5 | 6 | import {SafeMathInt, SafeMathUint} from "contracts/lib/SafeMathInt.sol"; 7 | 8 | contract SafeMathIntTest is Test { 9 | SafeMathUser safeMathUser; 10 | 11 | function setUp() public { 12 | safeMathUser = new SafeMathUser(); 13 | } 14 | 15 | function testToUint256Safe(int256 a) public { 16 | if (a < 0) { 17 | vm.expectRevert(stdError.assertionError); 18 | safeMathUser.toUint256Safe(a); 19 | } else assertEq(safeMathUser.toUint256Safe(a), uint256(a)); 20 | } 21 | 22 | function testToInt256Safe(uint256 a) public { 23 | if (a > uint256(type(int256).max)) { 24 | vm.expectRevert(stdError.assertionError); 25 | safeMathUser.toInt256Safe(a); 26 | } else assertEq(safeMathUser.toInt256Safe(a), int256(a)); 27 | } 28 | } 29 | 30 | /*////////////////////////////////////////////////////////////////////////// 31 | MOCKS 32 | //////////////////////////////////////////////////////////////////////////*/ 33 | 34 | contract SafeMathUser { 35 | function toUint256Safe(int256 a) external pure returns (uint256) { 36 | uint256 r = SafeMathInt.toUint256Safe(a); 37 | return r; 38 | } 39 | 40 | function toInt256Safe(uint256 a) external pure returns (int256) { 41 | int256 r = SafeMathUint.toInt256Safe(a); 42 | return r; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployEIP1559Burn.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {EIP1559Burn, IChildERC20Predicate} from "contracts/child/EIP1559Burn.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract EIP1559BurnDeployer is Script { 11 | function deployEIP1559Burn( 12 | address proxyAdmin, 13 | IChildERC20Predicate newChildERC20Predicate, 14 | address newBurnDestination 15 | ) internal returns (address logicAddr, address proxyAddr) { 16 | bytes memory initData = abi.encodeCall(EIP1559Burn.initialize, (newChildERC20Predicate, newBurnDestination)); 17 | 18 | vm.startBroadcast(); 19 | 20 | EIP1559Burn eip1559Burn = new EIP1559Burn(); 21 | 22 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(eip1559Burn), proxyAdmin, initData); 23 | 24 | vm.stopBroadcast(); 25 | 26 | logicAddr = address(eip1559Burn); 27 | proxyAddr = address(proxy); 28 | } 29 | } 30 | 31 | contract DeployEIP1559Burn is EIP1559BurnDeployer { 32 | function run( 33 | address proxyAdmin, 34 | IChildERC20Predicate newChildERC20Predicate, 35 | address newBurnDestination 36 | ) external returns (address logicAddr, address proxyAddr) { 37 | return deployEIP1559Burn(proxyAdmin, newChildERC20Predicate, newBurnDestination); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/child/RootMintableERC20PredicateAccessList.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import {RootMintableERC20Predicate} from "./RootMintableERC20Predicate.sol"; 5 | import {AccessList} from "../lib/AccessList.sol"; 6 | 7 | /** 8 | @title RootMintableERC20PredicateAccessList 9 | @author Polygon Technology (@QEDK) 10 | @notice Enables child-chain origin ERC20 token deposits and withdrawals (only from allowlisted address, and not from blocklisted addresses) across an arbitrary root chain and child chain 11 | */ 12 | // solhint-disable reason-string 13 | contract RootMintableERC20PredicateAccessList is AccessList, RootMintableERC20Predicate { 14 | constructor() { 15 | _disableInitializers(); 16 | } 17 | 18 | function initialize( 19 | address newL2StateSender, 20 | address newStateReceiver, 21 | address newChildERC20Predicate, 22 | address newChildTokenTemplate, 23 | bool newUseAllowList, 24 | bool newUseBlockList, 25 | address newOwner 26 | ) public virtual onlySystemCall initializer { 27 | _initialize(newL2StateSender, newStateReceiver, newChildERC20Predicate, newChildTokenTemplate); 28 | _initializeAccessList(newUseAllowList, newUseBlockList); 29 | _transferOwnership(newOwner); 30 | } 31 | 32 | function _beforeTokenDeposit() internal virtual override { 33 | _checkAccessList(); 34 | } 35 | 36 | // slither-disable-next-line unused-state,naming-convention 37 | uint256[50] private __gap; 38 | } 39 | -------------------------------------------------------------------------------- /contracts/common/README.md: -------------------------------------------------------------------------------- 1 | # Common 2 | 3 | ##### Contracts used by both root and child 4 | 5 | This directory contains a number of contracts which are used on both the root and child chains. It may have some overlap with `lib/` - `Merkle.sol` could likely be placed in either. (The other contracts in this directory are not actual library contracts, though.) 6 | 7 | The contracts in this directory are: 8 | 9 | - `BLS.sol`: BLS signature functions 10 | - `BN256G2.sol`: BN256 curve functions (this is the curve we use for BLS) 11 | - `Merkle.sol`: merkle verification 12 | 13 | There is extensive natspec on the contracts, along with markdown docs automatically generated from the natspec in the [`docs/`](../../docs/) directory at the project root. We'll provide a high-level overview of the contracts here. 14 | 15 | ## `BLS.sol` 16 | 17 | The BLS contract is used primarily to verify BLS signatures, which are used extensively by validators of the network. BLS signatures have a gas-friendly property which is the ability to verify a signature of aggregated signatures, which cuts down on the number of verifications that need ot be performed on block proposal and attestation drastically. 18 | 19 | ## `BN256G2.sol` 20 | 21 | BLS needs a curve. We use the BN256 curve. This contract exposes the mathematical functions needed to interact with the curve. 22 | 23 | ## `Merkle.sol` 24 | 25 | Merkle trees are a common form of compressing verification data in the suite. This contract exposes a function for verifying that a given leaf is a part of a merkle tree (given the root and proof). 26 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployChildERC20.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildERC20} from "contracts/child/ChildERC20.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildERC20Deployer is Script { 11 | function deployChildERC20( 12 | address proxyAdmin, 13 | address rootToken_, 14 | string memory name_, 15 | string memory symbol_, 16 | uint8 decimals_ 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall(ChildERC20.initialize, (rootToken_, name_, symbol_, decimals_)); 19 | 20 | vm.startBroadcast(); 21 | 22 | ChildERC20 childERC20 = new ChildERC20(); 23 | 24 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(childERC20), proxyAdmin, initData); 25 | 26 | vm.stopBroadcast(); 27 | 28 | logicAddr = address(childERC20); 29 | proxyAddr = address(proxy); 30 | } 31 | } 32 | 33 | contract DeployChildERC20 is ChildERC20Deployer { 34 | function run( 35 | address proxyAdmin, 36 | address rootToken_, 37 | string memory name_, 38 | string memory symbol_, 39 | uint8 decimals_ 40 | ) external returns (address logicAddr, address proxyAddr) { 41 | return deployChildERC20(proxyAdmin, rootToken_, name_, symbol_, decimals_); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /contracts/child/RootMintableERC721PredicateAccessList.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import {RootMintableERC721Predicate} from "./RootMintableERC721Predicate.sol"; 5 | import {AccessList} from "../lib/AccessList.sol"; 6 | 7 | /** 8 | @title RootMintableERC721PredicateAccessList 9 | @author Polygon Technology (@QEDK) 10 | @notice Enables child-chain origin ERC721 token deposits and withdrawals (only from allowlisted address, and not from blocklisted addresses) across an arbitrary root chain and child chain 11 | */ 12 | // solhint-disable reason-string 13 | contract RootMintableERC721PredicateAccessList is AccessList, RootMintableERC721Predicate { 14 | constructor() { 15 | _disableInitializers(); 16 | } 17 | 18 | function initialize( 19 | address newL2StateSender, 20 | address newStateReceiver, 21 | address newChildERC721Predicate, 22 | address newChildTokenTemplate, 23 | bool newUseAllowList, 24 | bool newUseBlockList, 25 | address newOwner 26 | ) public virtual onlySystemCall initializer { 27 | _initialize(newL2StateSender, newStateReceiver, newChildERC721Predicate, newChildTokenTemplate); 28 | _initializeAccessList(newUseAllowList, newUseBlockList); 29 | _transferOwnership(newOwner); 30 | } 31 | 32 | function _beforeTokenDeposit() internal virtual override { 33 | _checkAccessList(); 34 | } 35 | 36 | // slither-disable-next-line unused-state,naming-convention 37 | uint256[50] private __gap; 38 | } 39 | -------------------------------------------------------------------------------- /contracts/child/RootMintableERC1155PredicateAccessList.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import {RootMintableERC1155Predicate} from "./RootMintableERC1155Predicate.sol"; 5 | import {AccessList} from "../lib/AccessList.sol"; 6 | 7 | /** 8 | @title RootMintableERC1155PredicateAccessList 9 | @author Polygon Technology (@QEDK) 10 | @notice Enables child-chain origin ERC1155 token deposits and withdrawals (only from allowlisted address, and not from blocklisted addresses) across an arbitrary root chain and child chain 11 | */ 12 | // solhint-disable reason-string 13 | contract RootMintableERC1155PredicateAccessList is AccessList, RootMintableERC1155Predicate { 14 | constructor() { 15 | _disableInitializers(); 16 | } 17 | 18 | function initialize( 19 | address newL2StateSender, 20 | address newStateReceiver, 21 | address newChildERC1155Predicate, 22 | address newChildTokenTemplate, 23 | bool newUseAllowList, 24 | bool newUseBlockList, 25 | address newOwner 26 | ) public virtual onlySystemCall initializer { 27 | _initialize(newL2StateSender, newStateReceiver, newChildERC1155Predicate, newChildTokenTemplate); 28 | _initializeAccessList(newUseAllowList, newUseBlockList); 29 | _transferOwnership(newOwner); 30 | } 31 | 32 | function _beforeTokenDeposit() internal virtual override { 33 | _checkAccessList(); 34 | } 35 | 36 | // slither-disable-next-line unused-state,naming-convention 37 | uint256[50] private __gap; 38 | } 39 | -------------------------------------------------------------------------------- /docs/root/StateSender.md: -------------------------------------------------------------------------------- 1 | # StateSender 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### MAX_LENGTH 14 | 15 | ```solidity 16 | function MAX_LENGTH() external view returns (uint256) 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | 24 | #### Returns 25 | 26 | | Name | Type | Description | 27 | |---|---|---| 28 | | _0 | uint256 | undefined | 29 | 30 | ### counter 31 | 32 | ```solidity 33 | function counter() external view returns (uint256) 34 | ``` 35 | 36 | 37 | 38 | 39 | 40 | 41 | #### Returns 42 | 43 | | Name | Type | Description | 44 | |---|---|---| 45 | | _0 | uint256 | undefined | 46 | 47 | ### syncState 48 | 49 | ```solidity 50 | function syncState(address receiver, bytes data) external nonpayable 51 | ``` 52 | 53 | Generates sync state event based on receiver and data. Anyone can call this method to emit an event. Receiver on Polygon should add check based on sender. 54 | 55 | 56 | 57 | #### Parameters 58 | 59 | | Name | Type | Description | 60 | |---|---|---| 61 | | receiver | address | Receiver address on Polygon chain | 62 | | data | bytes | Data to send on Polygon chain | 63 | 64 | 65 | 66 | ## Events 67 | 68 | ### StateSynced 69 | 70 | ```solidity 71 | event StateSynced(uint256 indexed id, address indexed sender, address indexed receiver, bytes data) 72 | ``` 73 | 74 | 75 | 76 | 77 | 78 | #### Parameters 79 | 80 | | Name | Type | Description | 81 | |---|---|---| 82 | | id `indexed` | uint256 | undefined | 83 | | sender `indexed` | address | undefined | 84 | | receiver `indexed` | address | undefined | 85 | | data | bytes | undefined | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /contracts/child/ChildERC20PredicateAccessList.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import {ChildERC20Predicate} from "./ChildERC20Predicate.sol"; 5 | import {AccessList} from "../lib/AccessList.sol"; 6 | 7 | /** 8 | @title ChildERC20PredicateAccessList 9 | @author Polygon Technology (@QEDK) 10 | @notice Enables ERC20 token deposits and withdrawals (only from allowlisted address, and not from blocklisted addresses) across an arbitrary root chain and child chain 11 | */ 12 | // solhint-disable reason-string 13 | contract ChildERC20PredicateAccessList is AccessList, ChildERC20Predicate { 14 | constructor() { 15 | _disableInitializers(); 16 | } 17 | 18 | function initialize( 19 | address newL2StateSender, 20 | address newStateReceiver, 21 | address newRootERC20Predicate, 22 | address newChildTokenTemplate, 23 | address newNativeTokenRootAddress, 24 | bool newUseAllowList, 25 | bool newUseBlockList, 26 | address newOwner 27 | ) public virtual onlySystemCall initializer { 28 | _initialize( 29 | newL2StateSender, 30 | newStateReceiver, 31 | newRootERC20Predicate, 32 | newChildTokenTemplate, 33 | newNativeTokenRootAddress 34 | ); 35 | _initializeAccessList(newUseAllowList, newUseBlockList); 36 | _transferOwnership(newOwner); 37 | } 38 | 39 | function _beforeTokenWithdraw() internal virtual override { 40 | _checkAccessList(); 41 | } 42 | 43 | // slither-disable-next-line unused-state,naming-convention 44 | uint256[50] private __gap; 45 | } 46 | -------------------------------------------------------------------------------- /script/deployment/test/child/validator/DeployRewardPool.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {RewardPool} from "contracts/child/validator/RewardPool.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract RewardPoolDeployer is Script { 11 | function deployRewardPool( 12 | address proxyAdmin, 13 | address newRewardToken, 14 | address newRewardWallet, 15 | address newValidatorSet, 16 | uint256 newBaseReward 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | RewardPool.initialize, 20 | (newRewardToken, newRewardWallet, newValidatorSet, newBaseReward) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | RewardPool rewardPool = new RewardPool(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(rewardPool), proxyAdmin, initData); 28 | 29 | vm.stopBroadcast(); 30 | 31 | logicAddr = address(rewardPool); 32 | proxyAddr = address(proxy); 33 | } 34 | } 35 | 36 | contract DeployRewardPool is RewardPoolDeployer { 37 | function run( 38 | address proxyAdmin, 39 | address newRewardToken, 40 | address newRewardWallet, 41 | address newValidatorSet, 42 | uint256 newBaseReward 43 | ) external returns (address logicAddr, address proxyAddr) { 44 | return deployRewardPool(proxyAdmin, newRewardToken, newRewardWallet, newValidatorSet, newBaseReward); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /contracts/lib/README.md: -------------------------------------------------------------------------------- 1 | # Libraries 2 | ##### Library contracts 3 | 4 | This directory contains all library contracts in use in the contract suite, with the exception of third-party libraries (such as OpenZeppelin's Arrays Upgradeable, used in Child Validator Set) and the merkle verification contract (which is in [common](../common/)). We will give a high-level overview of the contracts, and then focus more on the high-level usage of the contracts dealing with the queues, pools, and validator tree. 5 | 6 | There is natspec on the contracts, along with markdown docs automatically generated from the natspec in the [`docs/`](../../docs/) directory at the project root. 7 | 8 | ## AccessList 9 | 10 | Edge implements protocol-level access lists for allowing (AllowList) or blocking (BlockList) access to various features of a Supernet, configurable by the administrators of the Supernet. Some of the potential applications of these lists require contracts to be able to check inclusion in the lists. The ability to do so is exposed by precompiles, this contract facilitates checking the precompile for membership. 11 | 12 | ## ChildManagerLib 13 | 14 | Library for use in a registry managing Supernets. 15 | 16 | ## EIP712MetaTransaction 17 | 18 | Helper contract for working with EIP712 19 | 20 | ## EIP712Upgradeable 21 | 22 | Implements an upgradeable modification of EIP712, adapted from OpenZeppelin. 23 | ## ModExp 24 | 25 | Focuses on mathematical operations related to cryptography. 26 | 27 | ## SafeMathInt 28 | 29 | Conversion between `uint256` and `int256`. 30 | 31 | ## StakeManagerLib 32 | 33 | Library for monitoring validator stake. 34 | 35 | ## WithdrawalQueue 36 | 37 | Library to manage withdrawals of funds from unstaking and rewards withdrawals. 38 | -------------------------------------------------------------------------------- /contracts/mocks/MockClones.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.8.0) (proxy/Clones.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for 8 | * deploying minimal proxy contracts, also known as "clones". 9 | * 10 | * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies 11 | * > a minimal bytecode implementation that delegates all calls to a known, fixed address. 12 | * 13 | * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` 14 | * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the 15 | * deterministic method. 16 | * 17 | * _Available since v3.4._ 18 | */ 19 | contract MockClones { 20 | /** 21 | * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. 22 | */ 23 | function predictDeterministicAddress( 24 | address implementation, 25 | bytes32 salt, 26 | address deployer 27 | ) external pure returns (address predicted) { 28 | /// @solidity memory-safe-assembly 29 | assembly { 30 | let ptr := mload(0x40) 31 | mstore(add(ptr, 0x38), deployer) 32 | mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) 33 | mstore(add(ptr, 0x14), implementation) 34 | mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) 35 | mstore(add(ptr, 0x58), salt) 36 | mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) 37 | predicted := keccak256(add(ptr, 0x43), 0x55) 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docs/child/L2StateSender.md: -------------------------------------------------------------------------------- 1 | # L2StateSender 2 | 3 | *Polygon Technology (@QEDK)* 4 | 5 | > L2StateSender 6 | 7 | Arbitrary message passing contract from L2 -> L1 8 | 9 | *There is no transaction execution on L1, only a commitment of the emitted events are stored* 10 | 11 | ## Methods 12 | 13 | ### MAX_LENGTH 14 | 15 | ```solidity 16 | function MAX_LENGTH() external view returns (uint256) 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | 24 | #### Returns 25 | 26 | | Name | Type | Description | 27 | |---|---|---| 28 | | _0 | uint256 | undefined | 29 | 30 | ### counter 31 | 32 | ```solidity 33 | function counter() external view returns (uint256) 34 | ``` 35 | 36 | 37 | 38 | 39 | 40 | 41 | #### Returns 42 | 43 | | Name | Type | Description | 44 | |---|---|---| 45 | | _0 | uint256 | undefined | 46 | 47 | ### syncState 48 | 49 | ```solidity 50 | function syncState(address receiver, bytes data) external nonpayable 51 | ``` 52 | 53 | Emits an event which is indexed by v3 validators and submitted as a commitment on L1 allowing for lazy execution 54 | 55 | 56 | 57 | #### Parameters 58 | 59 | | Name | Type | Description | 60 | |---|---|---| 61 | | receiver | address | Address of the message recipient on L1 | 62 | | data | bytes | Data to use in message call to recipient | 63 | 64 | 65 | 66 | ## Events 67 | 68 | ### L2StateSynced 69 | 70 | ```solidity 71 | event L2StateSynced(uint256 indexed id, address indexed sender, address indexed receiver, bytes data) 72 | ``` 73 | 74 | 75 | 76 | 77 | 78 | #### Parameters 79 | 80 | | Name | Type | Description | 81 | |---|---|---| 82 | | id `indexed` | uint256 | undefined | 83 | | sender `indexed` | address | undefined | 84 | | receiver `indexed` | address | undefined | 85 | | data | bytes | undefined | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployNativeERC20.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {NativeERC20} from "contracts/child/NativeERC20.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract NativeERC20Deployer is Script { 11 | function deployNativeERC20( 12 | address proxyAdmin, 13 | address predicate_, 14 | address rootToken_, 15 | string memory name_, 16 | string memory symbol_, 17 | uint8 decimals_, 18 | uint256 tokenSupply_ 19 | ) internal returns (address logicAddr, address proxyAddr) { 20 | bytes memory initData = abi.encodeCall( 21 | NativeERC20.initialize, 22 | (predicate_, rootToken_, name_, symbol_, decimals_, tokenSupply_) 23 | ); 24 | 25 | vm.startBroadcast(); 26 | 27 | NativeERC20 nativeERC20 = new NativeERC20(); 28 | 29 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(nativeERC20), proxyAdmin, initData); 30 | 31 | vm.stopBroadcast(); 32 | 33 | logicAddr = address(nativeERC20); 34 | proxyAddr = address(proxy); 35 | } 36 | } 37 | 38 | contract DeployNativeERC20 is NativeERC20Deployer { 39 | function run( 40 | address proxyAdmin, 41 | address predicate_, 42 | address rootToken_, 43 | string memory name_, 44 | string memory symbol_, 45 | uint8 decimals_, 46 | uint256 tokenSupply_ 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return deployNativeERC20(proxyAdmin, predicate_, rootToken_, name_, symbol_, decimals_, tokenSupply_); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /contracts/interfaces/root/IChildMintableERC1155Predicate.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "../child/IChildERC1155.sol"; 5 | import "./IL2StateReceiver.sol"; 6 | 7 | interface IChildMintableERC1155Predicate is IL2StateReceiver { 8 | event MintableERC1155Deposit( 9 | address indexed rootToken, 10 | address indexed childToken, 11 | address sender, 12 | address indexed receiver, 13 | uint256 tokenId, 14 | uint256 amount 15 | ); 16 | event MintableERC1155DepositBatch( 17 | address indexed rootToken, 18 | address indexed childToken, 19 | address indexed sender, 20 | address[] receivers, 21 | uint256[] tokenIds, 22 | uint256[] amounts 23 | ); 24 | event MintableERC1155Withdraw( 25 | address indexed rootToken, 26 | address indexed childToken, 27 | address sender, 28 | address indexed receiver, 29 | uint256 tokenId, 30 | uint256 amount 31 | ); 32 | event MintableERC1155WithdrawBatch( 33 | address indexed rootToken, 34 | address indexed childToken, 35 | address indexed sender, 36 | address[] receivers, 37 | uint256[] tokenIds, 38 | uint256[] amounts 39 | ); 40 | event MintableTokenMapped(address indexed rootToken, address indexed childToken); 41 | 42 | function initialize( 43 | address newStateSender, 44 | address newExitHelper, 45 | address newRootERC721Predicate, 46 | address newChildTokenTemplate 47 | ) external; 48 | 49 | function withdraw(IChildERC1155 childToken, uint256 tokenId, uint256 amount) external; 50 | 51 | function withdrawTo(IChildERC1155 childToken, address receiver, uint256 tokenId, uint256 amount) external; 52 | } 53 | -------------------------------------------------------------------------------- /contracts/interfaces/child/IRootMintableERC20Predicate.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; 5 | import "./IStateReceiver.sol"; 6 | 7 | interface IRootMintableERC20Predicate is IStateReceiver { 8 | event L2MintableERC20Deposit( 9 | address indexed rootToken, 10 | address indexed childToken, 11 | address depositor, 12 | address indexed receiver, 13 | uint256 amount 14 | ); 15 | event L2MintableERC20Withdraw( 16 | address indexed rootToken, 17 | address indexed childToken, 18 | address withdrawer, 19 | address indexed receiver, 20 | uint256 amount 21 | ); 22 | event L2MintableTokenMapped(address indexed rootToken, address indexed childToken); 23 | 24 | /** 25 | * @notice Function to deposit tokens from the depositor to themselves on the child chain 26 | * @param rootToken Address of the root token being deposited 27 | * @param amount Amount to deposit 28 | */ 29 | function deposit(IERC20Metadata rootToken, uint256 amount) external; 30 | 31 | /** 32 | * @notice Function to deposit tokens from the depositor to another address on the child chain 33 | * @param rootToken Address of the root token being deposited 34 | * @param amount Amount to deposit 35 | */ 36 | function depositTo(IERC20Metadata rootToken, address receiver, uint256 amount) external; 37 | 38 | /** 39 | * @notice Function to be used for token mapping 40 | * @param rootToken Address of the root token to map 41 | * @dev Called internally on deposit if token is not mapped already 42 | * @return address Address of the child token 43 | */ 44 | function mapToken(IERC20Metadata rootToken) external returns (address); 45 | } 46 | -------------------------------------------------------------------------------- /docs/interfaces/child/IChildERC20Predicate.md: -------------------------------------------------------------------------------- 1 | # IChildERC20Predicate 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### initialize 14 | 15 | ```solidity 16 | function initialize(address newL2StateSender, address newStateReceiver, address newRootERC20Predicate, address newChildTokenTemplate, address newNativeTokenRootAddress) external nonpayable 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | newL2StateSender | address | undefined | 28 | | newStateReceiver | address | undefined | 29 | | newRootERC20Predicate | address | undefined | 30 | | newChildTokenTemplate | address | undefined | 31 | | newNativeTokenRootAddress | address | undefined | 32 | 33 | ### onStateReceive 34 | 35 | ```solidity 36 | function onStateReceive(uint256, address sender, bytes data) external nonpayable 37 | ``` 38 | 39 | 40 | 41 | 42 | 43 | #### Parameters 44 | 45 | | Name | Type | Description | 46 | |---|---|---| 47 | | _0 | uint256 | undefined | 48 | | sender | address | undefined | 49 | | data | bytes | undefined | 50 | 51 | ### withdraw 52 | 53 | ```solidity 54 | function withdraw(contract IChildERC20 childToken, uint256 amount) external nonpayable 55 | ``` 56 | 57 | 58 | 59 | 60 | 61 | #### Parameters 62 | 63 | | Name | Type | Description | 64 | |---|---|---| 65 | | childToken | contract IChildERC20 | undefined | 66 | | amount | uint256 | undefined | 67 | 68 | ### withdrawTo 69 | 70 | ```solidity 71 | function withdrawTo(contract IChildERC20 childToken, address receiver, uint256 amount) external nonpayable 72 | ``` 73 | 74 | 75 | 76 | 77 | 78 | #### Parameters 79 | 80 | | Name | Type | Description | 81 | |---|---|---| 82 | | childToken | contract IChildERC20 | undefined | 83 | | receiver | address | undefined | 84 | | amount | uint256 | undefined | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /docs/interfaces/child/IChildERC1155Predicate.md: -------------------------------------------------------------------------------- 1 | # IChildERC1155Predicate 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### initialize 14 | 15 | ```solidity 16 | function initialize(address newL2StateSender, address newStateReceiver, address newRootERC721Predicate, address newChildTokenTemplate) external nonpayable 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | newL2StateSender | address | undefined | 28 | | newStateReceiver | address | undefined | 29 | | newRootERC721Predicate | address | undefined | 30 | | newChildTokenTemplate | address | undefined | 31 | 32 | ### onStateReceive 33 | 34 | ```solidity 35 | function onStateReceive(uint256, address sender, bytes data) external nonpayable 36 | ``` 37 | 38 | 39 | 40 | 41 | 42 | #### Parameters 43 | 44 | | Name | Type | Description | 45 | |---|---|---| 46 | | _0 | uint256 | undefined | 47 | | sender | address | undefined | 48 | | data | bytes | undefined | 49 | 50 | ### withdraw 51 | 52 | ```solidity 53 | function withdraw(contract IChildERC1155 childToken, uint256 tokenId, uint256 amount) external nonpayable 54 | ``` 55 | 56 | 57 | 58 | 59 | 60 | #### Parameters 61 | 62 | | Name | Type | Description | 63 | |---|---|---| 64 | | childToken | contract IChildERC1155 | undefined | 65 | | tokenId | uint256 | undefined | 66 | | amount | uint256 | undefined | 67 | 68 | ### withdrawTo 69 | 70 | ```solidity 71 | function withdrawTo(contract IChildERC1155 childToken, address receiver, uint256 tokenId, uint256 amount) external nonpayable 72 | ``` 73 | 74 | 75 | 76 | 77 | 78 | #### Parameters 79 | 80 | | Name | Type | Description | 81 | |---|---|---| 82 | | childToken | contract IChildERC1155 | undefined | 83 | | receiver | address | undefined | 84 | | tokenId | uint256 | undefined | 85 | | amount | uint256 | undefined | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /contracts/interfaces/root/IChildMintableERC721Predicate.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "../child/IChildERC721.sol"; 5 | import "./IL2StateReceiver.sol"; 6 | 7 | interface IChildMintableERC721Predicate is IL2StateReceiver { 8 | event MintableERC721Deposit( 9 | address indexed rootToken, 10 | address indexed childToken, 11 | address sender, 12 | address indexed receiver, 13 | uint256 tokenId 14 | ); 15 | event MintableERC721DepositBatch( 16 | address indexed rootToken, 17 | address indexed childToken, 18 | address indexed sender, 19 | address[] receivers, 20 | uint256[] tokenIds 21 | ); 22 | event MintableERC721Withdraw( 23 | address indexed rootToken, 24 | address indexed childToken, 25 | address sender, 26 | address indexed receiver, 27 | uint256 tokenId 28 | ); 29 | event MintableERC721WithdrawBatch( 30 | address indexed rootToken, 31 | address indexed childToken, 32 | address indexed sender, 33 | address[] receivers, 34 | uint256[] tokenIds 35 | ); 36 | event MintableTokenMapped(address indexed rootToken, address indexed childToken); 37 | 38 | function initialize( 39 | address newStateSender, 40 | address newExitHelper, 41 | address newRootERC721Predicate, 42 | address newChildTokenTemplate 43 | ) external; 44 | 45 | function onL2StateReceive(uint256 /* id */, address sender, bytes calldata data) external; 46 | 47 | function withdraw(IChildERC721 childToken, uint256 tokenId) external; 48 | 49 | function withdrawTo(IChildERC721 childToken, address receiver, uint256 tokenId) external; 50 | 51 | function withdrawBatch(IChildERC721 childToken, address[] calldata receivers, uint256[] calldata tokenIds) external; 52 | } 53 | -------------------------------------------------------------------------------- /contracts/lib/GenesisProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 6 | 7 | /** 8 | @title GenesisProxy 9 | @author Polygon Technology 10 | @notice wrapper for OpenZeppelin's Transparent Upgreadable Proxy, intended for use during genesis for genesis contracts 11 | @notice one GenesisProxy should be deployed for each genesis contract 12 | */ 13 | contract GenesisProxy is TransparentUpgradeableProxy { 14 | // keccak256("GenesisProxy INITIATOR_SLOT") 15 | bytes32 private constant INITIATOR_SLOT = hex"16561015e0650c143c10fb1907c52a56b654e2f0922ca3245bde5beff81a333d"; 16 | 17 | constructor() TransparentUpgradeableProxy(address(0), address(0), "") { 18 | revert(); 19 | } 20 | 21 | function protectSetUpProxy(address initiator) external { 22 | bytes32 protected; 23 | 24 | // slither-disable-next-line assembly 25 | assembly { 26 | protected := sload(INITIATOR_SLOT) 27 | sstore(INITIATOR_SLOT, initiator) 28 | } 29 | 30 | require(protected == "", "Already protected"); 31 | } 32 | 33 | function setUpProxy(address logic, address admin, bytes memory data) external { 34 | address initiator; 35 | 36 | // slither-disable-next-line assembly 37 | assembly { 38 | initiator := sload(INITIATOR_SLOT) 39 | } 40 | 41 | require(initiator != address(1), "Already set-up"); 42 | 43 | require(msg.sender == initiator, "Unauthorized"); 44 | 45 | // TransparentUpgradeableProxy constructor 46 | _changeAdmin(admin); 47 | 48 | // ERC1967Proxy constructor 49 | _upgradeToAndCall(logic, data, false); 50 | 51 | // slither-disable-next-line assembly 52 | assembly { 53 | sstore(INITIATOR_SLOT, 1) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /test/forge/utils/Assertions.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | // 💬 ABOUT 5 | // StdAssertions and custom assertions. 6 | 7 | // 🧩 MODULES 8 | import {StdAssertions} from "forge-std/StdAssertions.sol"; 9 | 10 | // 📦 BOILERPLATE 11 | import {StateReceiver} from "contracts/child/StateReceiver.sol"; 12 | import {Withdrawal} from "contracts/lib/WithdrawalQueue.sol"; 13 | import {RewardPool, Validator, Node, ValidatorTree} from "contracts/interfaces/lib/IValidator.sol"; 14 | 15 | // ⭐️ ASSERTIONS 16 | abstract contract Assertions is StdAssertions { 17 | function assertEq(Validator memory a, Validator memory b) internal virtual { 18 | _compareHash(keccak256(abi.encode(a)), keccak256(abi.encode(b)), "Validator"); 19 | } 20 | 21 | function assertEq(Validator memory a, Validator memory b, string memory err) internal virtual { 22 | if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { 23 | emit log_named_string("Error", err); 24 | assertEq(a, b); 25 | } 26 | } 27 | 28 | function assertEq(Node memory a, Node memory b) internal virtual { 29 | _compareHash(keccak256(abi.encode(a)), keccak256(abi.encode(b)), "Node"); 30 | } 31 | 32 | function assertEq(Withdrawal memory a, Withdrawal memory b) internal virtual { 33 | _compareHash(keccak256(abi.encode(a)), keccak256(abi.encode(b)), "Withdrawal"); 34 | } 35 | 36 | function assertEq( 37 | StateReceiver.StateSyncCommitment memory a, 38 | StateReceiver.StateSyncCommitment memory b 39 | ) internal virtual { 40 | _compareHash(keccak256(abi.encode(a)), keccak256(abi.encode(b)), "StateSyncCommitment"); 41 | } 42 | 43 | function _compareHash(bytes32 a, bytes32 b, string memory typeName) private { 44 | if (a != b) { 45 | emit log(string.concat("Error: a == b not satisfied [", typeName, "]")); 46 | fail(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/forge/root/StateSender.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@utils/Test.sol"; 5 | 6 | import {StateSender} from "contracts/root/StateSender.sol"; 7 | 8 | contract StateSenderTest is Test { 9 | event StateSynced(uint256 indexed id, address indexed sender, address indexed receiver, bytes data); 10 | 11 | StateSender stateSender; 12 | 13 | address receiver; 14 | bytes maxData; 15 | bytes moreThanMaxData; 16 | 17 | function setUp() public { 18 | stateSender = new StateSender(); 19 | receiver = makeAddr("receiver"); 20 | maxData = new bytes(stateSender.MAX_LENGTH()); 21 | moreThanMaxData = new bytes(stateSender.MAX_LENGTH() + 1); 22 | } 23 | 24 | function testConstructor() public { 25 | assertEq(stateSender.counter(), 0); 26 | } 27 | 28 | function testCannotSyncState_InvalidReceiver() public { 29 | vm.expectRevert("INVALID_RECEIVER"); 30 | stateSender.syncState(address(0), ""); 31 | } 32 | 33 | function testCannotSyncState_ExceedsMaxLength() public { 34 | vm.expectRevert("EXCEEDS_MAX_LENGTH"); 35 | stateSender.syncState(receiver, moreThanMaxData); 36 | } 37 | 38 | function testSyncState_EmitsEvent() public { 39 | vm.expectEmit(true, true, true, true); 40 | emit StateSynced(1, address(this), receiver, maxData); 41 | stateSender.syncState(receiver, maxData); 42 | } 43 | 44 | function testSyncState_IncreasesCounter() public { 45 | stateSender.syncState(receiver, maxData); 46 | stateSender.syncState(receiver, maxData); 47 | vm.expectRevert("EXCEEDS_MAX_LENGTH"); 48 | stateSender.syncState(receiver, moreThanMaxData); 49 | stateSender.syncState(receiver, maxData); 50 | vm.expectRevert("EXCEEDS_MAX_LENGTH"); 51 | stateSender.syncState(receiver, moreThanMaxData); 52 | 53 | assertEq(stateSender.counter(), 3); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /docs/lib/EIP712MetaTransaction.md: -------------------------------------------------------------------------------- 1 | # EIP712MetaTransaction 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### executeMetaTransaction 14 | 15 | ```solidity 16 | function executeMetaTransaction(address userAddress, bytes functionSignature, bytes32 sigR, bytes32 sigS, uint8 sigV) external nonpayable returns (bytes) 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | userAddress | address | undefined | 28 | | functionSignature | bytes | undefined | 29 | | sigR | bytes32 | undefined | 30 | | sigS | bytes32 | undefined | 31 | | sigV | uint8 | undefined | 32 | 33 | #### Returns 34 | 35 | | Name | Type | Description | 36 | |---|---|---| 37 | | _0 | bytes | undefined | 38 | 39 | ### getNonce 40 | 41 | ```solidity 42 | function getNonce(address user) external view returns (uint256 nonce) 43 | ``` 44 | 45 | 46 | 47 | 48 | 49 | #### Parameters 50 | 51 | | Name | Type | Description | 52 | |---|---|---| 53 | | user | address | undefined | 54 | 55 | #### Returns 56 | 57 | | Name | Type | Description | 58 | |---|---|---| 59 | | nonce | uint256 | undefined | 60 | 61 | ### invalidateNext 62 | 63 | ```solidity 64 | function invalidateNext(uint256 offset) external nonpayable 65 | ``` 66 | 67 | 68 | 69 | *Invalidates next "offset" number of nonces for the calling address* 70 | 71 | #### Parameters 72 | 73 | | Name | Type | Description | 74 | |---|---|---| 75 | | offset | uint256 | undefined | 76 | 77 | 78 | 79 | ## Events 80 | 81 | ### MetaTransactionExecuted 82 | 83 | ```solidity 84 | event MetaTransactionExecuted(address userAddress, address relayerAddress, bytes functionSignature) 85 | ``` 86 | 87 | 88 | 89 | 90 | 91 | #### Parameters 92 | 93 | | Name | Type | Description | 94 | |---|---|---| 95 | | userAddress | address | undefined | 96 | | relayerAddress | address | undefined | 97 | | functionSignature | bytes | undefined | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /docs/lib/GenesisProxy.md: -------------------------------------------------------------------------------- 1 | # GenesisProxy 2 | 3 | *Polygon Technology* 4 | 5 | > GenesisProxy 6 | 7 | wrapper for OpenZeppelin's Transparent Upgreadable Proxy, intended for use during genesis for genesis contractsone GenesisProxy should be deployed for each genesis contract 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### protectSetUpProxy 14 | 15 | ```solidity 16 | function protectSetUpProxy(address initiator) external nonpayable 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | initiator | address | undefined | 28 | 29 | ### setUpProxy 30 | 31 | ```solidity 32 | function setUpProxy(address logic, address admin, bytes data) external nonpayable 33 | ``` 34 | 35 | 36 | 37 | 38 | 39 | #### Parameters 40 | 41 | | Name | Type | Description | 42 | |---|---|---| 43 | | logic | address | undefined | 44 | | admin | address | undefined | 45 | | data | bytes | undefined | 46 | 47 | 48 | 49 | ## Events 50 | 51 | ### AdminChanged 52 | 53 | ```solidity 54 | event AdminChanged(address previousAdmin, address newAdmin) 55 | ``` 56 | 57 | 58 | 59 | *Emitted when the admin account has changed.* 60 | 61 | #### Parameters 62 | 63 | | Name | Type | Description | 64 | |---|---|---| 65 | | previousAdmin | address | undefined | 66 | | newAdmin | address | undefined | 67 | 68 | ### BeaconUpgraded 69 | 70 | ```solidity 71 | event BeaconUpgraded(address indexed beacon) 72 | ``` 73 | 74 | 75 | 76 | *Emitted when the beacon is changed.* 77 | 78 | #### Parameters 79 | 80 | | Name | Type | Description | 81 | |---|---|---| 82 | | beacon `indexed` | address | undefined | 83 | 84 | ### Upgraded 85 | 86 | ```solidity 87 | event Upgraded(address indexed implementation) 88 | ``` 89 | 90 | 91 | 92 | *Emitted when the implementation is upgraded.* 93 | 94 | #### Parameters 95 | 96 | | Name | Type | Description | 97 | |---|---|---| 98 | | implementation `indexed` | address | undefined | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /script/deployment/root/DeployRootERC721Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {RootERC721Predicate} from "contracts/root/RootERC721Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract RootERC721PredicateDeployer is Script { 11 | function deployRootERC721Predicate( 12 | address proxyAdmin, 13 | address newStateSender, 14 | address newExitHelper, 15 | address newChildERC721Predicate, 16 | address newChildTokenTemplate 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | RootERC721Predicate.initialize, 20 | (newStateSender, newExitHelper, newChildERC721Predicate, newChildTokenTemplate) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | RootERC721Predicate rootERC721Predicate = new RootERC721Predicate(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 28 | address(rootERC721Predicate), 29 | proxyAdmin, 30 | initData 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | 35 | logicAddr = address(rootERC721Predicate); 36 | proxyAddr = address(proxy); 37 | } 38 | } 39 | 40 | contract DeployRootERC721Predicate is RootERC721PredicateDeployer { 41 | function run( 42 | address proxyAdmin, 43 | address newStateSender, 44 | address newExitHelper, 45 | address newChildERC721Predicate, 46 | address newChildTokenTemplate 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return 49 | deployRootERC721Predicate( 50 | proxyAdmin, 51 | newStateSender, 52 | newExitHelper, 53 | newChildERC721Predicate, 54 | newChildTokenTemplate 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /script/deployment/root/DeployRootERC1155Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {RootERC1155Predicate} from "contracts/root/RootERC1155Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract RootERC1155PredicateDeployer is Script { 11 | function deployRootERC1155Predicate( 12 | address proxyAdmin, 13 | address newStateSender, 14 | address newExitHelper, 15 | address newChildERC1155Predicate, 16 | address newChildTokenTemplate 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | RootERC1155Predicate.initialize, 20 | (newStateSender, newExitHelper, newChildERC1155Predicate, newChildTokenTemplate) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | RootERC1155Predicate rootERC1155Predicate = new RootERC1155Predicate(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 28 | address(rootERC1155Predicate), 29 | proxyAdmin, 30 | initData 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | 35 | logicAddr = address(rootERC1155Predicate); 36 | proxyAddr = address(proxy); 37 | } 38 | } 39 | 40 | contract DeployRootERC1155Predicate is RootERC1155PredicateDeployer { 41 | function run( 42 | address proxyAdmin, 43 | address newStateSender, 44 | address newExitHelper, 45 | address newChildERC1155Predicate, 46 | address newChildTokenTemplate 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return 49 | deployRootERC1155Predicate( 50 | proxyAdmin, 51 | newStateSender, 52 | newExitHelper, 53 | newChildERC1155Predicate, 54 | newChildTokenTemplate 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /contracts/interfaces/child/IChildERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) 3 | 4 | pragma solidity 0.8.19; 5 | 6 | import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; 7 | 8 | /** 9 | * @dev Interface of IChildERC20 10 | */ 11 | interface IChildERC20 is IERC20MetadataUpgradeable { 12 | /** 13 | * @dev Sets the values for {rootToken}, {name}, {symbol} and {decimals}. 14 | * 15 | * All these values are immutable: they can only be set once during 16 | * initialization. 17 | */ 18 | function initialize(address rootToken_, string calldata name_, string calldata symbol_, uint8 decimals_) external; 19 | 20 | /** 21 | * @notice Returns predicate address controlling the child token 22 | * @return address Returns the address of the predicate 23 | */ 24 | function predicate() external view returns (address); 25 | 26 | /** 27 | * @notice Returns predicate address controlling the child token 28 | * @return address Returns the address of the predicate 29 | */ 30 | function rootToken() external view returns (address); 31 | 32 | /** 33 | * @notice Mints an amount of tokens to a particular address 34 | * @dev Can only be called by the predicate address 35 | * @param account Account of the user to mint the tokens to 36 | * @param amount Amount of tokens to mint to the account 37 | * @return bool Returns true if function call is successful 38 | */ 39 | function mint(address account, uint256 amount) external returns (bool); 40 | 41 | /** 42 | * @notice Burns an amount of tokens from a particular address 43 | * @dev Can only be called by the predicate address 44 | * @param account Account of the user to burn the tokens from 45 | * @param amount Amount of tokens to burn from the account 46 | * @return bool Returns true if function call is successful 47 | */ 48 | function burn(address account, uint256 amount) external returns (bool); 49 | } 50 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployChildERC721Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildERC721Predicate} from "contracts/child/ChildERC721Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildERC721PredicateDeployer is Script { 11 | function deployChildERC721Predicate( 12 | address proxyAdmin, 13 | address newL2StateSender, 14 | address newStateReceiver, 15 | address newRootERC721Predicate, 16 | address newChildTokenTemplate 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | ChildERC721Predicate.initialize, 20 | (newL2StateSender, newStateReceiver, newRootERC721Predicate, newChildTokenTemplate) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | ChildERC721Predicate childERC721Predicate = new ChildERC721Predicate(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 28 | address(childERC721Predicate), 29 | proxyAdmin, 30 | initData 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | 35 | logicAddr = address(childERC721Predicate); 36 | proxyAddr = address(proxy); 37 | } 38 | } 39 | 40 | contract DeployChildERC721Predicate is ChildERC721PredicateDeployer { 41 | function run( 42 | address proxyAdmin, 43 | address newL2StateSender, 44 | address newStateReceiver, 45 | address newRootERC721Predicate, 46 | address newChildTokenTemplate 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return 49 | deployChildERC721Predicate( 50 | proxyAdmin, 51 | newL2StateSender, 52 | newStateReceiver, 53 | newRootERC721Predicate, 54 | newChildTokenTemplate 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployChildERC1155Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildERC1155Predicate} from "contracts/child/ChildERC1155Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildERC1155PredicateDeployer is Script { 11 | function deployChildERC1155Predicate( 12 | address proxyAdmin, 13 | address newL2StateSender, 14 | address newStateReceiver, 15 | address newRootERC1155Predicate, 16 | address newChildTokenTemplate 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | ChildERC1155Predicate.initialize, 20 | (newL2StateSender, newStateReceiver, newRootERC1155Predicate, newChildTokenTemplate) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | ChildERC1155Predicate childERC1155Predicate = new ChildERC1155Predicate(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 28 | address(childERC1155Predicate), 29 | proxyAdmin, 30 | initData 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | 35 | logicAddr = address(childERC1155Predicate); 36 | proxyAddr = address(proxy); 37 | } 38 | } 39 | 40 | contract DeployChildERC1155Predicate is ChildERC1155PredicateDeployer { 41 | function run( 42 | address proxyAdmin, 43 | address newL2StateSender, 44 | address newStateReceiver, 45 | address newRootERC1155Predicate, 46 | address newChildTokenTemplate 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return 49 | deployChildERC1155Predicate( 50 | proxyAdmin, 51 | newL2StateSender, 52 | newStateReceiver, 53 | newRootERC1155Predicate, 54 | newChildTokenTemplate 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /docs/interfaces/child/validator/IRewardPool.md: -------------------------------------------------------------------------------- 1 | # IRewardPool 2 | 3 | *Polygon Technology (@gretzke)* 4 | 5 | > IRewardPool 6 | 7 | Distributes rewards to validators for committed epochs 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### distributeRewardFor 14 | 15 | ```solidity 16 | function distributeRewardFor(uint256 epochId, Uptime[] uptime) external nonpayable 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | epochId | uint256 | undefined | 28 | | uptime | Uptime[] | undefined | 29 | 30 | ### paidRewardPerEpoch 31 | 32 | ```solidity 33 | function paidRewardPerEpoch(uint256 epochId) external view returns (uint256) 34 | ``` 35 | 36 | returns the total reward paid for the given epoch 37 | 38 | 39 | 40 | #### Parameters 41 | 42 | | Name | Type | Description | 43 | |---|---|---| 44 | | epochId | uint256 | undefined | 45 | 46 | #### Returns 47 | 48 | | Name | Type | Description | 49 | |---|---|---| 50 | | _0 | uint256 | undefined | 51 | 52 | ### pendingRewards 53 | 54 | ```solidity 55 | function pendingRewards(address account) external view returns (uint256) 56 | ``` 57 | 58 | returns the pending reward for the given account 59 | 60 | 61 | 62 | #### Parameters 63 | 64 | | Name | Type | Description | 65 | |---|---|---| 66 | | account | address | undefined | 67 | 68 | #### Returns 69 | 70 | | Name | Type | Description | 71 | |---|---|---| 72 | | _0 | uint256 | undefined | 73 | 74 | ### withdrawReward 75 | 76 | ```solidity 77 | function withdrawReward() external nonpayable 78 | ``` 79 | 80 | withdraws pending rewards for the sender (validator) 81 | 82 | 83 | 84 | 85 | 86 | 87 | ## Events 88 | 89 | ### RewardDistributed 90 | 91 | ```solidity 92 | event RewardDistributed(uint256 indexed epochId, uint256 totalReward) 93 | ``` 94 | 95 | 96 | 97 | 98 | 99 | #### Parameters 100 | 101 | | Name | Type | Description | 102 | |---|---|---| 103 | | epochId `indexed` | uint256 | undefined | 104 | | totalReward | uint256 | undefined | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /script/deployment/test/child/validator/DeployValidatorSet.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ValidatorSet, ValidatorInit} from "contracts/child/validator/ValidatorSet.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ValidatorSetDeployer is Script { 11 | function deployValidatorSet( 12 | address proxyAdmin, 13 | address newStateSender, 14 | address newStateReceiver, 15 | address newRootChainManager, 16 | uint256 newEpochSize, 17 | ValidatorInit[] memory initialValidators 18 | ) internal returns (address logicAddr, address proxyAddr) { 19 | bytes memory initData = abi.encodeCall( 20 | ValidatorSet.initialize, 21 | (newStateSender, newStateReceiver, newRootChainManager, newEpochSize, initialValidators) 22 | ); 23 | 24 | vm.startBroadcast(); 25 | 26 | ValidatorSet validatorSet = new ValidatorSet(); 27 | 28 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 29 | address(validatorSet), 30 | proxyAdmin, 31 | initData 32 | ); 33 | 34 | vm.stopBroadcast(); 35 | 36 | logicAddr = address(validatorSet); 37 | proxyAddr = address(proxy); 38 | } 39 | } 40 | 41 | contract DeployValidatorSet is ValidatorSetDeployer { 42 | function run( 43 | address proxyAdmin, 44 | address newStateSender, 45 | address newStateReceiver, 46 | address newRootChainManager, 47 | uint256 newEpochSize, 48 | ValidatorInit[] memory initialValidators 49 | ) external returns (address logicAddr, address proxyAddr) { 50 | return 51 | deployValidatorSet( 52 | proxyAdmin, 53 | newStateSender, 54 | newStateReceiver, 55 | newRootChainManager, 56 | newEpochSize, 57 | initialValidators 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /script/deployment/root/DeployChildMintableERC20Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildMintableERC20Predicate} from "contracts/root/ChildMintableERC20Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildMintableERC20PredicateDeployer is Script { 11 | function deployChildMintableERC20Predicate( 12 | address proxyAdmin, 13 | address newStateSender, 14 | address newExitHelper, 15 | address newRootERC20Predicate, 16 | address newChildTokenTemplate 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | ChildMintableERC20Predicate.initialize, 20 | (newStateSender, newExitHelper, newRootERC20Predicate, newChildTokenTemplate) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | ChildMintableERC20Predicate childMintableERC20Predicate = new ChildMintableERC20Predicate(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 28 | address(childMintableERC20Predicate), 29 | proxyAdmin, 30 | initData 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | 35 | logicAddr = address(childMintableERC20Predicate); 36 | proxyAddr = address(proxy); 37 | } 38 | } 39 | 40 | contract DeployChildMintableERC20Predicate is ChildMintableERC20PredicateDeployer { 41 | function run( 42 | address proxyAdmin, 43 | address newStateSender, 44 | address newExitHelper, 45 | address newRootERC20Predicate, 46 | address newChildTokenTemplate 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return 49 | deployChildMintableERC20Predicate( 50 | proxyAdmin, 51 | newStateSender, 52 | newExitHelper, 53 | newRootERC20Predicate, 54 | newChildTokenTemplate 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /script/deployment/root/DeployChildMintableERC721Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildMintableERC721Predicate} from "contracts/root/ChildMintableERC721Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildMintableERC721PredicateDeployer is Script { 11 | function deployChildMintableERC721Predicate( 12 | address proxyAdmin, 13 | address newStateSender, 14 | address newExitHelper, 15 | address newRootERC721Predicate, 16 | address newChildTokenTemplate 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | ChildMintableERC721Predicate.initialize, 20 | (newStateSender, newExitHelper, newRootERC721Predicate, newChildTokenTemplate) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | ChildMintableERC721Predicate childMintableERC721Predicate = new ChildMintableERC721Predicate(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 28 | address(childMintableERC721Predicate), 29 | proxyAdmin, 30 | initData 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | 35 | logicAddr = address(childMintableERC721Predicate); 36 | proxyAddr = address(proxy); 37 | } 38 | } 39 | 40 | contract DeployChildMintableERC721Predicate is ChildMintableERC721PredicateDeployer { 41 | function run( 42 | address proxyAdmin, 43 | address newStateSender, 44 | address newExitHelper, 45 | address newRootERC721Predicate, 46 | address newChildTokenTemplate 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return 49 | deployChildMintableERC721Predicate( 50 | proxyAdmin, 51 | newStateSender, 52 | newExitHelper, 53 | newRootERC721Predicate, 54 | newChildTokenTemplate 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployRootMintableERC20Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {RootMintableERC20Predicate} from "contracts/child/RootMintableERC20Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract RootMintableERC20PredicateDeployer is Script { 11 | function deployRootMintableERC20Predicate( 12 | address proxyAdmin, 13 | address newL2StateSender, 14 | address newStateReceiver, 15 | address newChildERC20Predicate, 16 | address newChildTokenTemplate 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | RootMintableERC20Predicate.initialize, 20 | (newL2StateSender, newStateReceiver, newChildERC20Predicate, newChildTokenTemplate) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | RootMintableERC20Predicate rootMintableERC20Predicate = new RootMintableERC20Predicate(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 28 | address(rootMintableERC20Predicate), 29 | proxyAdmin, 30 | initData 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | 35 | logicAddr = address(rootMintableERC20Predicate); 36 | proxyAddr = address(proxy); 37 | } 38 | } 39 | 40 | contract DeployRootMintableERC20Predicate is RootMintableERC20PredicateDeployer { 41 | function run( 42 | address proxyAdmin, 43 | address newL2StateSender, 44 | address newStateReceiver, 45 | address newChildERC20Predicate, 46 | address newChildTokenTemplate 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return 49 | deployRootMintableERC20Predicate( 50 | proxyAdmin, 51 | newL2StateSender, 52 | newStateReceiver, 53 | newChildERC20Predicate, 54 | newChildTokenTemplate 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployRootMintableERC721Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {RootMintableERC721Predicate} from "contracts/child/RootMintableERC721Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract RootMintableERC721PredicateDeployer is Script { 11 | function deployRootMintableERC721Predicate( 12 | address proxyAdmin, 13 | address newL2StateSender, 14 | address newStateReceiver, 15 | address newChildERC721Predicate, 16 | address newChildTokenTemplate 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | RootMintableERC721Predicate.initialize, 20 | (newL2StateSender, newStateReceiver, newChildERC721Predicate, newChildTokenTemplate) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | RootMintableERC721Predicate rootMintableERC721Predicate = new RootMintableERC721Predicate(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 28 | address(rootMintableERC721Predicate), 29 | proxyAdmin, 30 | initData 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | 35 | logicAddr = address(rootMintableERC721Predicate); 36 | proxyAddr = address(proxy); 37 | } 38 | } 39 | 40 | contract DeployRootMintableERC721Predicate is RootMintableERC721PredicateDeployer { 41 | function run( 42 | address proxyAdmin, 43 | address newL2StateSender, 44 | address newStateReceiver, 45 | address newChildERC721Predicate, 46 | address newChildTokenTemplate 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return 49 | deployRootMintableERC721Predicate( 50 | proxyAdmin, 51 | newL2StateSender, 52 | newStateReceiver, 53 | newChildERC721Predicate, 54 | newChildTokenTemplate 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /script/deployment/root/DeployChildMintableERC1155Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildMintableERC1155Predicate} from "contracts/root/ChildMintableERC1155Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildMintableERC1155PredicateDeployer is Script { 11 | function deployChildMintableERC1155Predicate( 12 | address proxyAdmin, 13 | address newStateSender, 14 | address newExitHelper, 15 | address newRootERC1155Predicate, 16 | address newChildTokenTemplate 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | ChildMintableERC1155Predicate.initialize, 20 | (newStateSender, newExitHelper, newRootERC1155Predicate, newChildTokenTemplate) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | ChildMintableERC1155Predicate childMintableERC1155Predicate = new ChildMintableERC1155Predicate(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 28 | address(childMintableERC1155Predicate), 29 | proxyAdmin, 30 | initData 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | 35 | logicAddr = address(childMintableERC1155Predicate); 36 | proxyAddr = address(proxy); 37 | } 38 | } 39 | 40 | contract DeployChildMintableERC1155Predicate is ChildMintableERC1155PredicateDeployer { 41 | function run( 42 | address proxyAdmin, 43 | address newStateSender, 44 | address newExitHelper, 45 | address newRootERC1155Predicate, 46 | address newChildTokenTemplate 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return 49 | deployChildMintableERC1155Predicate( 50 | proxyAdmin, 51 | newStateSender, 52 | newExitHelper, 53 | newRootERC1155Predicate, 54 | newChildTokenTemplate 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /script/deployment/root/DeployRootERC20Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {RootERC20Predicate} from "contracts/root/RootERC20Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract RootERC20PredicateDeployer is Script { 11 | function deployRootERC20Predicate( 12 | address proxyAdmin, 13 | address newStateSender, 14 | address newExitHelper, 15 | address newChildERC20Predicate, 16 | address newChildTokenTemplate, 17 | address nativeTokenRootAddress 18 | ) internal returns (address logicAddr, address proxyAddr) { 19 | bytes memory initData = abi.encodeCall( 20 | RootERC20Predicate.initialize, 21 | (newStateSender, newExitHelper, newChildERC20Predicate, newChildTokenTemplate, nativeTokenRootAddress) 22 | ); 23 | 24 | vm.startBroadcast(); 25 | 26 | RootERC20Predicate rootERC20Predicate = new RootERC20Predicate(); 27 | 28 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 29 | address(rootERC20Predicate), 30 | proxyAdmin, 31 | initData 32 | ); 33 | 34 | vm.stopBroadcast(); 35 | 36 | logicAddr = address(rootERC20Predicate); 37 | proxyAddr = address(proxy); 38 | } 39 | } 40 | 41 | contract DeployRootERC20Predicate is RootERC20PredicateDeployer { 42 | function run( 43 | address proxyAdmin, 44 | address newStateSender, 45 | address newExitHelper, 46 | address newChildERC20Predicate, 47 | address newChildTokenTemplate, 48 | address nativeTokenRootAddress 49 | ) external returns (address logicAddr, address proxyAddr) { 50 | return 51 | deployRootERC20Predicate( 52 | proxyAdmin, 53 | newStateSender, 54 | newExitHelper, 55 | newChildERC20Predicate, 56 | newChildTokenTemplate, 57 | nativeTokenRootAddress 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployRootMintableERC1155Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {RootMintableERC1155Predicate} from "contracts/child/RootMintableERC1155Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract RootMintableERC1155PredicateDeployer is Script { 11 | function deployRootMintableERC1155Predicate( 12 | address proxyAdmin, 13 | address newL2StateSender, 14 | address newStateReceiver, 15 | address newChildERC1155Predicate, 16 | address newChildTokenTemplate 17 | ) internal returns (address logicAddr, address proxyAddr) { 18 | bytes memory initData = abi.encodeCall( 19 | RootMintableERC1155Predicate.initialize, 20 | (newL2StateSender, newStateReceiver, newChildERC1155Predicate, newChildTokenTemplate) 21 | ); 22 | 23 | vm.startBroadcast(); 24 | 25 | RootMintableERC1155Predicate rootMintableERC1155Predicate = new RootMintableERC1155Predicate(); 26 | 27 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 28 | address(rootMintableERC1155Predicate), 29 | proxyAdmin, 30 | initData 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | 35 | logicAddr = address(rootMintableERC1155Predicate); 36 | proxyAddr = address(proxy); 37 | } 38 | } 39 | 40 | contract DeployRootMintableERC1155Predicate is RootMintableERC1155PredicateDeployer { 41 | function run( 42 | address proxyAdmin, 43 | address newL2StateSender, 44 | address newStateReceiver, 45 | address newChildERC1155Predicate, 46 | address newChildTokenTemplate 47 | ) external returns (address logicAddr, address proxyAddr) { 48 | return 49 | deployRootMintableERC1155Predicate( 50 | proxyAdmin, 51 | newL2StateSender, 52 | newStateReceiver, 53 | newChildERC1155Predicate, 54 | newChildTokenTemplate 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /contracts/interfaces/child/INativeERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) 3 | 4 | pragma solidity 0.8.19; 5 | 6 | import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; 7 | 8 | /** 9 | * @dev Interface of INativeERC20 10 | */ 11 | interface INativeERC20 is IERC20MetadataUpgradeable { 12 | /** 13 | * @dev Sets the values for {rootToken}, {name}, {symbol} and {decimals}. 14 | * 15 | * All these values are immutable: they can only be set once during 16 | * initialization. 17 | */ 18 | function initialize( 19 | address predicate_, 20 | address rootToken_, 21 | string calldata name_, 22 | string calldata symbol_, 23 | uint8 decimals_, 24 | uint256 tokenSupply_ 25 | ) external; 26 | 27 | /** 28 | * @notice Returns predicate address controlling the child token 29 | * @return address Returns the address of the predicate 30 | */ 31 | function predicate() external view returns (address); 32 | 33 | /** 34 | * @notice Returns corresponding root token address for the child native token 35 | * @return address Returns the root token address 36 | */ 37 | function rootToken() external view returns (address); 38 | 39 | /** 40 | * @notice Mints an amount of tokens to a particular address 41 | * @dev Can only be called by the predicate address 42 | * @param account Account of the user to mint the tokens to 43 | * @param amount Amount of tokens to mint to the account 44 | * @return bool Returns true if function call is successful 45 | */ 46 | function mint(address account, uint256 amount) external returns (bool); 47 | 48 | /** 49 | * @notice Burns an amount of tokens from a particular address 50 | * @dev Can only be called by the predicate address 51 | * @param account Account of the user to burn the tokens from 52 | * @param amount Amount of tokens to burn from the account 53 | * @return bool Returns true if function call is successful 54 | */ 55 | function burn(address account, uint256 amount) external returns (bool); 56 | } 57 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployNativeERC20Mintable.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {NativeERC20Mintable} from "contracts/child/NativeERC20Mintable.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract NativeERC20MintableDeployer is Script { 11 | function deployNativeERC20Mintable( 12 | address proxyAdmin, 13 | address predicate_, 14 | address owner_, 15 | address rootToken_, 16 | string memory name_, 17 | string memory symbol_, 18 | uint8 decimals_, 19 | uint256 tokenSupply_ 20 | ) internal returns (address logicAddr, address proxyAddr) { 21 | bytes memory initData = abi.encodeCall( 22 | NativeERC20Mintable.initialize, 23 | (predicate_, owner_, rootToken_, name_, symbol_, decimals_, tokenSupply_) 24 | ); 25 | 26 | vm.startBroadcast(); 27 | 28 | NativeERC20Mintable nativeERC20Mintable = new NativeERC20Mintable(); 29 | 30 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 31 | address(nativeERC20Mintable), 32 | proxyAdmin, 33 | initData 34 | ); 35 | 36 | vm.stopBroadcast(); 37 | 38 | logicAddr = address(nativeERC20Mintable); 39 | proxyAddr = address(proxy); 40 | } 41 | } 42 | 43 | contract DeployNativeERC20Mintable is NativeERC20MintableDeployer { 44 | function run( 45 | address proxyAdmin, 46 | address predicate_, 47 | address owner_, 48 | address rootToken_, 49 | string memory name_, 50 | string memory symbol_, 51 | uint8 decimals_, 52 | uint256 tokenSupply_ 53 | ) external returns (address logicAddr, address proxyAddr) { 54 | return 55 | deployNativeERC20Mintable( 56 | proxyAdmin, 57 | predicate_, 58 | owner_, 59 | rootToken_, 60 | name_, 61 | symbol_, 62 | decimals_, 63 | tokenSupply_ 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /contracts/interfaces/root/IRootERC20Predicate.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; 5 | import "./IL2StateReceiver.sol"; 6 | 7 | interface IRootERC20Predicate is IL2StateReceiver { 8 | struct ERC20BridgeEvent { 9 | address rootToken; 10 | address childToken; 11 | address sender; 12 | address receiver; 13 | } 14 | 15 | event ERC20Deposit( 16 | address indexed rootToken, 17 | address indexed childToken, 18 | address depositor, 19 | address indexed receiver, 20 | uint256 amount 21 | ); 22 | event ERC20Withdraw( 23 | address indexed rootToken, 24 | address indexed childToken, 25 | address withdrawer, 26 | address indexed receiver, 27 | uint256 amount 28 | ); 29 | event TokenMapped(address indexed rootToken, address indexed childToken); 30 | 31 | /** 32 | * @notice Function to deposit tokens from the depositor to themselves on the child chain 33 | * @param rootToken Address of the root token being deposited 34 | * @param amount Amount to deposit 35 | */ 36 | function deposit(IERC20Metadata rootToken, uint256 amount) external; 37 | 38 | /** 39 | * @notice Function to deposit tokens from the depositor to another address on the child chain 40 | * @param rootToken Address of the root token being deposited 41 | * @param amount Amount to deposit 42 | */ 43 | function depositTo(IERC20Metadata rootToken, address receiver, uint256 amount) external; 44 | 45 | /** 46 | * @notice Function to be used for token mapping 47 | * @param rootToken Address of the root token to map 48 | * @dev Called internally on deposit if token is not mapped already 49 | * @return address Address of the child token 50 | */ 51 | function mapToken(IERC20Metadata rootToken) external returns (address); 52 | 53 | /** 54 | * @notice Function that retrieves rootchain token that represents Supernets native token 55 | * @return address Address of rootchain token (mapped to Supernets native token) 56 | */ 57 | function nativeTokenRoot() external returns (address); 58 | } 59 | -------------------------------------------------------------------------------- /contracts/child/EIP1559Burn.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; 5 | import "../interfaces/child/IChildERC20.sol"; 6 | import "../interfaces/child/IChildERC20Predicate.sol"; 7 | 8 | /** 9 | @title EIP1559Burn 10 | @author Polygon Technology (@QEDK) 11 | @notice Burns the native token on root chain as an ERC20 12 | */ 13 | contract EIP1559Burn is Initializable { 14 | IChildERC20Predicate public childERC20Predicate; 15 | address public burnDestination; 16 | IChildERC20 private constant _NATIVE_TOKEN = IChildERC20(0x0000000000000000000000000000000000001010); 17 | 18 | event NativeTokenBurnt(address indexed burner, uint256 amount); 19 | 20 | // slither-disable-next-line locked-ether 21 | receive() external payable {} // solhint-disable-line no-empty-blocks 22 | 23 | constructor() { 24 | _disableInitializers(); 25 | } 26 | 27 | /** 28 | * @notice Initialization function for EIP1559 burn contract 29 | * @param newChildERC20Predicate Address of the ERC20 predicate on child chain 30 | * @param newBurnDestination Address on the root chain to burn the tokens and send to 31 | * @dev Can only be called once 32 | */ 33 | function initialize(IChildERC20Predicate newChildERC20Predicate, address newBurnDestination) external initializer { 34 | require(address(newChildERC20Predicate) != address(0), "EIP1559Burn: BAD_INITIALIZATION"); 35 | childERC20Predicate = newChildERC20Predicate; 36 | // slither-disable-next-line missing-zero-check 37 | burnDestination = newBurnDestination; 38 | } 39 | 40 | /** 41 | * @notice Function to burn native tokens on child chain and send them to burn destination on root 42 | * @dev Takes the entire current native token balance and burns it 43 | */ 44 | function withdraw() external { 45 | require(address(childERC20Predicate) != address(0), "EIP1559Burn: UNINITIALIZED"); 46 | 47 | uint256 balance = address(this).balance; 48 | 49 | childERC20Predicate.withdrawTo(_NATIVE_TOKEN, burnDestination, balance); 50 | // slither-disable-next-line reentrancy-events 51 | emit NativeTokenBurnt(msg.sender, balance); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /docs/interfaces/child/IChildERC721Predicate.md: -------------------------------------------------------------------------------- 1 | # IChildERC721Predicate 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### initialize 14 | 15 | ```solidity 16 | function initialize(address newL2StateSender, address newStateReceiver, address newRootERC721Predicate, address newChildTokenTemplate) external nonpayable 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | #### Parameters 24 | 25 | | Name | Type | Description | 26 | |---|---|---| 27 | | newL2StateSender | address | undefined | 28 | | newStateReceiver | address | undefined | 29 | | newRootERC721Predicate | address | undefined | 30 | | newChildTokenTemplate | address | undefined | 31 | 32 | ### onStateReceive 33 | 34 | ```solidity 35 | function onStateReceive(uint256, address sender, bytes data) external nonpayable 36 | ``` 37 | 38 | 39 | 40 | 41 | 42 | #### Parameters 43 | 44 | | Name | Type | Description | 45 | |---|---|---| 46 | | _0 | uint256 | undefined | 47 | | sender | address | undefined | 48 | | data | bytes | undefined | 49 | 50 | ### withdraw 51 | 52 | ```solidity 53 | function withdraw(contract IChildERC721 childToken, uint256 tokenId) external nonpayable 54 | ``` 55 | 56 | 57 | 58 | 59 | 60 | #### Parameters 61 | 62 | | Name | Type | Description | 63 | |---|---|---| 64 | | childToken | contract IChildERC721 | undefined | 65 | | tokenId | uint256 | undefined | 66 | 67 | ### withdrawBatch 68 | 69 | ```solidity 70 | function withdrawBatch(contract IChildERC721 childToken, address[] receivers, uint256[] tokenIds) external nonpayable 71 | ``` 72 | 73 | 74 | 75 | 76 | 77 | #### Parameters 78 | 79 | | Name | Type | Description | 80 | |---|---|---| 81 | | childToken | contract IChildERC721 | undefined | 82 | | receivers | address[] | undefined | 83 | | tokenIds | uint256[] | undefined | 84 | 85 | ### withdrawTo 86 | 87 | ```solidity 88 | function withdrawTo(contract IChildERC721 childToken, address receiver, uint256 tokenId) external nonpayable 89 | ``` 90 | 91 | 92 | 93 | 94 | 95 | #### Parameters 96 | 97 | | Name | Type | Description | 98 | |---|---|---| 99 | | childToken | contract IChildERC721 | undefined | 100 | | receiver | address | undefined | 101 | | tokenId | uint256 | undefined | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployChildERC20Predicate.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildERC20Predicate} from "contracts/child/ChildERC20Predicate.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildERC20PredicateDeployer is Script { 11 | function deployChildERC20Predicate( 12 | address proxyAdmin, 13 | address newL2StateSender, 14 | address newStateReceiver, 15 | address newRootERC20Predicate, 16 | address newChildTokenTemplate, 17 | address newNativeTokenRootAddress 18 | ) internal returns (address logicAddr, address proxyAddr) { 19 | bytes memory initData = abi.encodeCall( 20 | ChildERC20Predicate.initialize, 21 | ( 22 | newL2StateSender, 23 | newStateReceiver, 24 | newRootERC20Predicate, 25 | newChildTokenTemplate, 26 | newNativeTokenRootAddress 27 | ) 28 | ); 29 | 30 | vm.startBroadcast(); 31 | 32 | ChildERC20Predicate childERC20Predicate = new ChildERC20Predicate(); 33 | 34 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 35 | address(childERC20Predicate), 36 | proxyAdmin, 37 | initData 38 | ); 39 | 40 | vm.stopBroadcast(); 41 | 42 | logicAddr = address(childERC20Predicate); 43 | proxyAddr = address(proxy); 44 | } 45 | } 46 | 47 | contract DeployChildERC20Predicate is ChildERC20PredicateDeployer { 48 | function run( 49 | address proxyAdmin, 50 | address newL2StateSender, 51 | address newStateReceiver, 52 | address newRootERC20Predicate, 53 | address newChildTokenTemplate, 54 | address newNativeTokenRootAddress 55 | ) external returns (address logicAddr, address proxyAddr) { 56 | return 57 | deployChildERC20Predicate( 58 | proxyAdmin, 59 | newL2StateSender, 60 | newStateReceiver, 61 | newRootERC20Predicate, 62 | newChildTokenTemplate, 63 | newNativeTokenRootAddress 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /docs/child/EIP1559Burn.md: -------------------------------------------------------------------------------- 1 | # EIP1559Burn 2 | 3 | *Polygon Technology (@QEDK)* 4 | 5 | > EIP1559Burn 6 | 7 | Burns the native token on root chain as an ERC20 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### burnDestination 14 | 15 | ```solidity 16 | function burnDestination() external view returns (address) 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | 24 | #### Returns 25 | 26 | | Name | Type | Description | 27 | |---|---|---| 28 | | _0 | address | undefined | 29 | 30 | ### childERC20Predicate 31 | 32 | ```solidity 33 | function childERC20Predicate() external view returns (contract IChildERC20Predicate) 34 | ``` 35 | 36 | 37 | 38 | 39 | 40 | 41 | #### Returns 42 | 43 | | Name | Type | Description | 44 | |---|---|---| 45 | | _0 | contract IChildERC20Predicate | undefined | 46 | 47 | ### initialize 48 | 49 | ```solidity 50 | function initialize(contract IChildERC20Predicate newChildERC20Predicate, address newBurnDestination) external nonpayable 51 | ``` 52 | 53 | Initialization function for EIP1559 burn contract 54 | 55 | *Can only be called once* 56 | 57 | #### Parameters 58 | 59 | | Name | Type | Description | 60 | |---|---|---| 61 | | newChildERC20Predicate | contract IChildERC20Predicate | Address of the ERC20 predicate on child chain | 62 | | newBurnDestination | address | Address on the root chain to burn the tokens and send to | 63 | 64 | ### withdraw 65 | 66 | ```solidity 67 | function withdraw() external nonpayable 68 | ``` 69 | 70 | Function to burn native tokens on child chain and send them to burn destination on root 71 | 72 | *Takes the entire current native token balance and burns it* 73 | 74 | 75 | 76 | 77 | ## Events 78 | 79 | ### Initialized 80 | 81 | ```solidity 82 | event Initialized(uint8 version) 83 | ``` 84 | 85 | 86 | 87 | *Triggered when the contract has been initialized or reinitialized.* 88 | 89 | #### Parameters 90 | 91 | | Name | Type | Description | 92 | |---|---|---| 93 | | version | uint8 | undefined | 94 | 95 | ### NativeTokenBurnt 96 | 97 | ```solidity 98 | event NativeTokenBurnt(address indexed burner, uint256 amount) 99 | ``` 100 | 101 | 102 | 103 | 104 | 105 | #### Parameters 106 | 107 | | Name | Type | Description | 108 | |---|---|---| 109 | | burner `indexed` | address | undefined | 110 | | amount | uint256 | undefined | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /contracts/root/staking/StakeManagerStakingData.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | /** 5 | * @title StakeManagerStakingData 6 | * @notice Holds all staking related data. 7 | * Note that this is contract is designed to be included in StakeManager. It is upgradeable. 8 | */ 9 | abstract contract StakeManagerStakingData { 10 | // slither-disable-next-line naming-convention 11 | uint256 internal _totalStake; 12 | // validator => child => amount 13 | mapping(address => mapping(uint256 => uint256)) private _stakes; 14 | // child chain id => total stake 15 | mapping(uint256 => uint256) private _totalStakePerChild; 16 | // validator address => stake across all child chains. 17 | mapping(address => uint256) private _totalStakes; 18 | // validator address => withdrawable stake. 19 | mapping(address => uint256) private _withdrawableStakes; 20 | 21 | function _addStake(address validator, uint256 id, uint256 amount) internal { 22 | _stakes[validator][id] += amount; 23 | _totalStakePerChild[id] += amount; 24 | _totalStakes[validator] += amount; 25 | _totalStake += amount; 26 | } 27 | 28 | function _removeStake(address validator, uint256 id, uint256 amount) internal { 29 | _stakes[validator][id] -= amount; 30 | _totalStakePerChild[id] -= amount; 31 | _totalStakes[validator] -= amount; 32 | _totalStake -= amount; 33 | _withdrawableStakes[validator] += amount; 34 | } 35 | 36 | function _withdrawStake(address validator, uint256 amount) internal { 37 | _withdrawableStakes[validator] -= amount; 38 | } 39 | 40 | function _withdrawableStakeOf(address validator) internal view returns (uint256 amount) { 41 | amount = _withdrawableStakes[validator]; 42 | } 43 | 44 | function _totalStakeOfChild(uint256 id) internal view returns (uint256 amount) { 45 | amount = _totalStakePerChild[id]; 46 | } 47 | 48 | function _stakeOf(address validator, uint256 id) internal view returns (uint256 amount) { 49 | amount = _stakes[validator][id]; 50 | } 51 | 52 | function _totalStakeOf(address validator) internal view returns (uint256 amount) { 53 | amount = _totalStakes[validator]; 54 | } 55 | 56 | // Storage gap 57 | // slither-disable-next-line unused-state,naming-convention 58 | uint256[50] private __gap; 59 | } 60 | -------------------------------------------------------------------------------- /contracts/root/staking/StakeManagerChildData.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | /** 5 | * @title StakeManagerChildData 6 | * @notice Holds data to allow look-up between child chain manager contract address and child chain id. 7 | * Note that this is contract is designed to be included in StakeManager. It is upgradeable. 8 | */ 9 | abstract contract StakeManagerChildData { 10 | // Highest child chain id allocated thus far. Child chain id 0x00 is an invalid id. 11 | // slither-disable-next-line naming-convention 12 | uint256 internal _counter; 13 | // child chain id to child chain manager contract address. 14 | mapping(uint256 => address) private _managers; 15 | // child chain manager contract address to child chain id. 16 | // slither-disable-next-line naming-convention 17 | mapping(address => uint256) internal _ids; 18 | 19 | /** 20 | * @notice Register a child chain manager contract and allocate a child chain id. 21 | * @param manager Child chain manager contract address. 22 | * @return id Child chain id allocated for the child chain. 23 | */ 24 | function _registerChild(address manager) internal returns (uint256 id) { 25 | require(manager != address(0), "StakeManagerChildData: INVALID_ADDRESS"); 26 | unchecked { 27 | id = ++_counter; 28 | } 29 | _managers[id] = manager; 30 | _ids[manager] = id; 31 | } 32 | 33 | /** 34 | * @notice Get the child chain manager contract that corresponds to a child chain id. 35 | * @param id Child chain id. 36 | * @return manager Child chain manager contract address. 37 | */ 38 | function _managerOf(uint256 id) internal view returns (address manager) { 39 | manager = _managers[id]; 40 | require(manager != address(0), "StakeManagerChildData: INVALID_ID"); 41 | } 42 | 43 | /** 44 | * @notice Get the child chain id that corresponds to a child chain manager contract. 45 | * @param manager Child chain manager contract address. 46 | * @return id Child chain id. 47 | */ 48 | function _idFor(address manager) internal view returns (uint256 id) { 49 | id = _ids[manager]; 50 | require(id != 0, "StakeManagerChildData: INVALID_MANAGER"); 51 | } 52 | 53 | // Storage gap 54 | // slither-disable-next-line unused-state,naming-convention 55 | uint256[50] private __gap; 56 | } 57 | -------------------------------------------------------------------------------- /hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import "@nomicfoundation/hardhat-toolbox"; 2 | import "@openzeppelin/hardhat-upgrades"; 3 | import "@primitivefi/hardhat-dodoc"; 4 | import * as dotenv from "dotenv"; 5 | import { HardhatUserConfig } from "hardhat/config"; 6 | 7 | dotenv.config(); 8 | 9 | const config: HardhatUserConfig = { 10 | solidity: { 11 | compilers: [ 12 | { 13 | version: "0.8.19", 14 | settings: { 15 | optimizer: { 16 | enabled: true, 17 | runs: 115, 18 | }, 19 | outputSelection: { 20 | "*": { 21 | "*": ["storageLayout"], 22 | }, 23 | }, 24 | }, 25 | }, 26 | ], 27 | }, 28 | networks: { 29 | root: { 30 | url: process.env.ROOT_RPC || "", 31 | accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 32 | }, 33 | rootTest: { 34 | url: process.env.ROOT_TEST_RPC || "", 35 | accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 36 | }, 37 | child: { 38 | url: process.env.CHILD_RPC || "", 39 | accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 40 | }, 41 | childTest: { 42 | url: process.env.CHILD_TEST_RPC || "", 43 | accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 44 | }, 45 | hardhat: { 46 | // allow impersonation of smart contracts without modifying balance 47 | gasPrice: 0, 48 | hardfork: "berlin", 49 | }, 50 | }, 51 | gasReporter: { 52 | enabled: (process.env.REPORT_GAS as unknown as boolean) || false, 53 | currency: "USD", 54 | }, 55 | etherscan: { 56 | apiKey: { 57 | mainnet: process.env.ETHERSCAN_API_KEY !== undefined ? process.env.ETHERSCAN_API_KEY : "", 58 | goerli: process.env.ETHERSCAN_API_KEY !== undefined ? process.env.ETHERSCAN_API_KEY : "", 59 | polygon: process.env.POLYGONSCAN_API_KEY !== undefined ? process.env.POLYGONSCAN_API_KEY : "", 60 | polygonMumbai: process.env.POLYGONSCAN_API_KEY !== undefined ? process.env.POLYGONSCAN_API_KEY : "", 61 | }, 62 | }, 63 | mocha: { 64 | timeout: 100000000, 65 | }, 66 | dodoc: { 67 | // uncomment to stop docs from autogenerating each compile 68 | // runOnCompile: false, 69 | exclude: ["mocks", "openzeppelin/contracts", "openzeppelin/contracts-upgradeable"], 70 | }, 71 | }; 72 | 73 | export default config; 74 | -------------------------------------------------------------------------------- /contracts/lib/AccessList.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; 5 | import {IAddressList} from "../interfaces/IAddressList.sol"; 6 | import {System} from "../child/System.sol"; 7 | 8 | /** 9 | @title AccessList 10 | @author Polygon Technology (@QEDK, @wschwab) 11 | @notice Checks the access lists to see if an address is allowed and not blocked 12 | */ 13 | contract AccessList is Ownable2StepUpgradeable, System { 14 | bool private _useAllowList; 15 | bool private _useBlockList; 16 | 17 | event AllowListUsageSet(uint256 indexed block, bool indexed status); 18 | event BlockListUsageSet(uint256 indexed block, bool indexed status); 19 | 20 | function setAllowList(bool newUseAllowList) external onlyOwner { 21 | _useAllowList = newUseAllowList; 22 | emit AllowListUsageSet(block.number, newUseAllowList); 23 | } 24 | 25 | function setBlockList(bool newUseBlockList) external onlyOwner { 26 | _useBlockList = newUseBlockList; 27 | emit BlockListUsageSet(block.number, newUseBlockList); 28 | } 29 | 30 | function _checkAccessList() internal view { 31 | if (_useAllowList) { 32 | // solhint-disable avoid-low-level-calls 33 | // slither-disable-next-line low-level-calls 34 | (bool allowSuccess, bytes memory allowlistRes) = ALLOWLIST_PRECOMPILE.staticcall{gas: READ_ADDRESSLIST_GAS}( 35 | abi.encodeWithSelector(IAddressList.readAddressList.selector, msg.sender) 36 | ); 37 | require(allowSuccess && abi.decode(allowlistRes, (uint256)) > 0, "DISALLOWED_SENDER"); 38 | } 39 | if (_useBlockList) { 40 | // slither-disable-next-line low-level-calls 41 | (bool blockSuccess, bytes memory blocklistRes) = BLOCKLIST_PRECOMPILE.staticcall{gas: READ_ADDRESSLIST_GAS}( 42 | abi.encodeWithSelector(IAddressList.readAddressList.selector, msg.sender) 43 | ); 44 | require(blockSuccess && abi.decode(blocklistRes, (uint256)) != 1, "BLOCKED_SENDER"); 45 | } 46 | } 47 | 48 | function _initializeAccessList(bool __useAllowList, bool __useBlockList) internal { 49 | _useAllowList = __useAllowList; 50 | _useBlockList = __useBlockList; 51 | } 52 | 53 | // slither-disable-next-line unused-state,naming-convention 54 | uint256[50] private __gap; 55 | } 56 | -------------------------------------------------------------------------------- /contracts/interfaces/root/staking/IStakeManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "../../../interfaces/root/staking/ISupernetManager.sol"; 5 | 6 | /** 7 | @title IStakeManager 8 | @author Polygon Technology (@gretzke) 9 | @notice Manages stakes for all child chains 10 | */ 11 | interface IStakeManager { 12 | event ChildManagerRegistered(uint256 indexed id, address indexed manager); 13 | event StakeAdded(uint256 indexed id, address indexed validator, uint256 amount); 14 | event StakeRemoved(uint256 indexed id, address indexed validator, uint256 amount); 15 | event StakeWithdrawn(address indexed validator, address indexed recipient, uint256 amount); 16 | 17 | /// @notice registers a new child chain with the staking contract 18 | /// @return id of the child chain 19 | function registerChildChain(address manager) external returns (uint256 id); 20 | 21 | /// @notice called by a validator to stake for a child chain 22 | function stakeFor(uint256 id, uint256 amount) external; 23 | 24 | /// @notice called by child manager contract to release a validator's stake 25 | function releaseStakeOf(address validator, uint256 amount) external; 26 | 27 | /// @notice allows a validator to withdraw released stake 28 | function withdrawStake(address to, uint256 amount) external; 29 | 30 | /// @notice returns the amount of stake a validator can withdraw 31 | function withdrawableStake(address validator) external view returns (uint256 amount); 32 | 33 | /// @notice returns the total amount staked for all child chains 34 | function totalStake() external view returns (uint256 amount); 35 | 36 | /// @notice returns the total amount staked for a child chain 37 | function totalStakeOfChild(uint256 id) external view returns (uint256 amount); 38 | 39 | /// @notice returns the total amount staked of a validator for all child chains 40 | function totalStakeOf(address validator) external view returns (uint256 amount); 41 | 42 | /// @notice returns the amount staked by a validator for a child chain 43 | function stakeOf(address validator, uint256 id) external view returns (uint256 amount); 44 | 45 | /// @notice returns the child chain manager contract for a child chain 46 | function managerOf(uint256 id) external view returns (ISupernetManager manager); 47 | 48 | /// @notice returns the child id for a child chain manager contract 49 | function idFor(address manager) external view returns (uint256 id); 50 | } 51 | -------------------------------------------------------------------------------- /test/child/L2StateSender.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import * as hre from "hardhat"; 3 | import { ethers } from "hardhat"; 4 | import { L2StateSender } from "../../typechain-types"; 5 | 6 | describe("L2StateSender", () => { 7 | let l2StateSender: L2StateSender, accounts: any[]; // we use any so we can access address directly from object 8 | before(async () => { 9 | accounts = await ethers.getSigners(); 10 | const l2StateSenderFactory = await ethers.getContractFactory("L2StateSender"); 11 | l2StateSender = (await l2StateSenderFactory.deploy()) as L2StateSender; 12 | 13 | await l2StateSender.deployed(); 14 | }); 15 | 16 | it("validate initialization", async () => { 17 | expect(await l2StateSender.MAX_LENGTH()).to.equal(2048); 18 | expect(await l2StateSender.counter()).to.equal(0); 19 | }); 20 | 21 | it("sync state fail: exceeds max length", async () => { 22 | const data = ethers.utils.hexlify(ethers.utils.randomBytes(2049)); 23 | await expect(l2StateSender.syncState(accounts[2].address, data)).to.be.revertedWith("EXCEEDS_MAX_LENGTH"); 24 | }); 25 | 26 | it("sync state fail: invalid receiver", async () => { 27 | const data = ethers.utils.hexlify(ethers.utils.randomBytes(2048)); 28 | await expect(l2StateSender.syncState(ethers.constants.AddressZero, data)).to.be.revertedWith("INVALID_RECEIVER"); 29 | }); 30 | 31 | it("sync state", async () => { 32 | const rounds = Math.floor(Math.random() * 10 + 2); 33 | let counter = 0; 34 | for (let i = 0; i < rounds; i++) { 35 | const sender = ethers.Wallet.createRandom(); 36 | const receiver = ethers.Wallet.createRandom(); 37 | const data = ethers.utils.hexlify(ethers.utils.randomBytes(2048)); 38 | await hre.network.provider.request({ 39 | method: "hardhat_impersonateAccount", 40 | params: [sender.address], 41 | }); 42 | await hre.network.provider.send("hardhat_setBalance", [ 43 | sender.address, 44 | "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 45 | ]); 46 | const newl2StateSender = await l2StateSender.connect(await ethers.getSigner(sender.address)); 47 | const tx = await newl2StateSender.syncState(receiver.address, data); 48 | const receipt = await tx.wait(); 49 | expect(receipt.events[0]?.args?.id).to.equal(counter + 1); 50 | expect(receipt.events[0]?.args?.sender).to.equal(sender.address); 51 | expect(receipt.events[0]?.args?.receiver).to.equal(receiver.address); 52 | expect(await l2StateSender.counter()).to.equal(++counter); 53 | } 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | node_modules 107 | .env 108 | coverage 109 | coverage.json 110 | typechain 111 | typechain-types 112 | 113 | #Hardhat files 114 | cache 115 | artifacts 116 | 117 | .openzeppelin/ 118 | 119 | # Foundry 120 | # Compiler files 121 | forge-cache/ 122 | out/ 123 | forge-coverage/ 124 | lcov.info 125 | # Ignores development broadcast logs 126 | !/broadcast 127 | /broadcast/* 128 | /broadcast/*/31337/ 129 | 130 | .DS_Store 131 | .vscode/ -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | hardhat.config.ts 2 | scripts 3 | test 4 | docs 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Microbundle cache 62 | .rpt2_cache/ 63 | .rts2_cache_cjs/ 64 | .rts2_cache_es/ 65 | .rts2_cache_umd/ 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | .env.test 79 | 80 | # parcel-bundler cache (https://parceljs.org/) 81 | .cache 82 | 83 | # Next.js build output 84 | .next 85 | 86 | # Nuxt.js build / generate output 87 | .nuxt 88 | dist 89 | 90 | # Gatsby files 91 | .cache/ 92 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 93 | # https://nextjs.org/blog/next-9-1#public-directory-support 94 | # public 95 | 96 | # vuepress build output 97 | .vuepress/dist 98 | 99 | # Serverless directories 100 | .serverless/ 101 | 102 | # FuseBox cache 103 | .fusebox/ 104 | 105 | # DynamoDB Local files 106 | .dynamodb/ 107 | 108 | # TernJS port file 109 | .tern-port 110 | 111 | node_modules 112 | .env 113 | coverage 114 | coverage.json 115 | typechain 116 | typechain-types 117 | 118 | #Hardhat files 119 | cache 120 | artifacts 121 | 122 | .openzeppelin/ 123 | 124 | # Foundry 125 | # Compiler files 126 | forge-cache/ 127 | out/ 128 | # Ignores development broadcast logs 129 | !/broadcast 130 | /broadcast/* 131 | /broadcast/*/31337/ 132 | 133 | .DS_Store 134 | -------------------------------------------------------------------------------- /test/common/BN256G2.test.ts: -------------------------------------------------------------------------------- 1 | import { assert } from "chai"; 2 | import { BigNumber } from "ethers"; 3 | import { ethers } from "hardhat"; 4 | import * as mcl from "../../ts/mcl"; 5 | import { BN256G2 } from "../../typechain-types"; 6 | 7 | const DOMAIN = ethers.utils.arrayify(ethers.utils.hexlify(ethers.utils.randomBytes(32))); 8 | 9 | describe("BN256G2", async () => { 10 | let bn256G2: BN256G2; 11 | before(async function () { 12 | await mcl.init(); 13 | const bn256G2Factory = await ethers.getContractFactory("BN256G2"); 14 | bn256G2 = (await bn256G2Factory.deploy()) as BN256G2; 15 | await bn256G2.deployTransaction.wait(); 16 | }); 17 | it("Addition on G2 (1 point)", async function () { 18 | const pks = []; 19 | const rawPks: mcl.PublicKey[] = []; 20 | for (let i = 0; i <= 1; i++) { 21 | const { pubkey, secret } = mcl.newKeyPair(); 22 | rawPks.push(pubkey); 23 | pks.push(mcl.g2ToHex(pubkey)); 24 | } 25 | const bignumberPk = mcl.g2ToHex(mcl.aggregatePks(rawPks)).map((elem) => BigNumber.from(elem)); 26 | assert.deepEqual( 27 | await bn256G2.ecTwistAdd(pks[0][0], pks[0][1], pks[0][2], pks[0][3], pks[1][0], pks[1][1], pks[1][2], pks[1][3]), 28 | bignumberPk 29 | ); 30 | }); 31 | it("Addition on G2 (10 points)", async function () { 32 | const pks = []; 33 | const rawPks: mcl.PublicKey[] = []; 34 | for (let i = 0; i < 10; i++) { 35 | const { pubkey, secret } = mcl.newKeyPair(); 36 | rawPks.push(pubkey); 37 | pks.push(mcl.g2ToHex(pubkey)); 38 | } 39 | const bignumberPk = mcl.g2ToHex(mcl.aggregatePks(rawPks)).map((elem) => BigNumber.from(elem)); 40 | let aggPk: mcl.PublicKey = pks[0]; 41 | for (let i = 1; i < 10; i++) { 42 | aggPk = await bn256G2.ecTwistAdd( 43 | aggPk[0], 44 | aggPk[1], 45 | aggPk[2], 46 | aggPk[3], 47 | pks[i][0], 48 | pks[i][1], 49 | pks[i][2], 50 | pks[i][3] 51 | ); 52 | } 53 | assert.deepEqual(aggPk, bignumberPk); 54 | }); 55 | it("Multiplication on G2 (10 points)", async function () { 56 | for (let i = 0; i < 10; i++) { 57 | const { pubkey, secret } = mcl.newKeyPair(); 58 | const pk = mcl.g2ToHex(pubkey); 59 | const scalar = Math.floor(Math.random() * (9999 - 1) + 1); // pick a random number from 1 - 9999 60 | const pubkeyMultiplied = mcl.mulG2FrInt(pubkey, scalar); 61 | const bigNumberG2 = mcl.g2ToHex(pubkeyMultiplied).map((elem) => BigNumber.from(elem)); 62 | assert.deepEqual(await bn256G2.ecTwistMul(scalar, pk[0], pk[1], pk[2], pk[3]), bigNumberG2); 63 | } 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /test/forge/root/staking/deployment/DeployStakeManager.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Test.sol"; 6 | 7 | import {DeployStakeManager} from "script/deployment/root/staking/DeployStakeManager.s.sol"; 8 | 9 | import {StakeManager} from "contracts/root/staking/StakeManager.sol"; 10 | import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 11 | 12 | contract DeployStakeManagerTest is Test { 13 | DeployStakeManager private deployer; 14 | 15 | address logicAddr; 16 | address proxyAddr; 17 | 18 | StakeManager internal proxyAsStakeManager; 19 | ITransparentUpgradeableProxy internal proxy; 20 | 21 | address proxyAdmin; 22 | address newStakingToken; 23 | 24 | function setUp() public { 25 | deployer = new DeployStakeManager(); 26 | 27 | proxyAdmin = makeAddr("proxyAdmin"); 28 | newStakingToken = makeAddr("newStakingToken"); 29 | 30 | (logicAddr, proxyAddr) = deployer.run(proxyAdmin, newStakingToken); 31 | _recordProxy(proxyAddr); 32 | } 33 | 34 | function testRun() public { 35 | vm.startPrank(proxyAdmin); 36 | 37 | assertEq(proxy.admin(), proxyAdmin); 38 | assertEq(proxy.implementation(), logicAddr); 39 | 40 | vm.stopPrank(); 41 | } 42 | 43 | function testInitialization() public { 44 | vm.expectRevert("Initializable: contract is already initialized"); 45 | proxyAsStakeManager.initialize(newStakingToken); 46 | 47 | assertEq( 48 | vm.load(address(proxyAsStakeManager), bytes32(uint(109))), 49 | bytes32(bytes.concat(hex"000000000000000000000000", abi.encodePacked(newStakingToken))) 50 | ); 51 | } 52 | 53 | function testLogicChange() public { 54 | address newLogicAddr = makeAddr("newLogicAddr"); 55 | vm.etch(newLogicAddr, hex"00"); 56 | 57 | vm.startPrank(proxyAdmin); 58 | 59 | proxy.upgradeTo(newLogicAddr); 60 | assertEq(proxy.implementation(), newLogicAddr); 61 | 62 | vm.stopPrank(); 63 | } 64 | 65 | function testAdminChange() public { 66 | address newAdmin = makeAddr("newAdmin"); 67 | 68 | vm.prank(proxyAdmin); 69 | proxy.changeAdmin(newAdmin); 70 | 71 | vm.prank(newAdmin); 72 | assertEq(proxy.admin(), newAdmin); 73 | } 74 | 75 | function _recordProxy(address _proxyAddr) internal { 76 | proxyAsStakeManager = StakeManager(_proxyAddr); 77 | proxy = ITransparentUpgradeableProxy(payable(address(_proxyAddr))); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /test/forge/child/generateMsg.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | import * as mcl from "../../../ts/mcl"; 3 | const input = process.argv[2]; 4 | 5 | const DOMAIN = ethers.utils.arrayify(ethers.utils.solidityKeccak256(["string"], ["DOMAIN_CHILD_VALIDATOR_SET"])); 6 | const CHAIN_ID = 31337; 7 | let blockHashs: any[] = []; 8 | let signatures: any[] = []; 9 | 10 | async function generateMsg() { 11 | await mcl.init(); 12 | const message = ethers.utils.hexlify(ethers.utils.toUtf8Bytes("polygon-v3-validator")); 13 | const { pubkey, secret } = mcl.newKeyPair(); 14 | const { signature, messagePoint } = mcl.sign(message, secret, DOMAIN); 15 | 16 | const parsedPubkey = mcl.g2ToHex(pubkey); 17 | const parsedSignature = mcl.g1ToHex(signature); 18 | 19 | const messagePointForInit = mcl.g1ToHex( 20 | mcl.hashToPoint(ethers.utils.hexlify(ethers.utils.toUtf8Bytes("polygon-v3-validator")), DOMAIN) 21 | ); 22 | 23 | generateSignature(); 24 | 25 | const output = ethers.utils.defaultAbiCoder.encode( 26 | ["uint256[2]", "uint256[2]", "uint256[4]", "bytes32[]", "bytes[]"], 27 | [messagePointForInit, parsedSignature, parsedPubkey, blockHashs, signatures] 28 | ); 29 | 30 | console.log(output); 31 | } 32 | 33 | function generateSignature() { 34 | const blockNumber = 0; 35 | const pbftRound = 0; 36 | const epochId = 0; 37 | const blockHash1 = ethers.utils.randomBytes(32); 38 | const blockHash2 = ethers.utils.randomBytes(32); 39 | const signature1 = ethers.utils.keccak256( 40 | ethers.utils.defaultAbiCoder.encode( 41 | ["uint", "uint", "uint", "bytes32"], 42 | [blockNumber, pbftRound, epochId, blockHash1] 43 | ) 44 | ); 45 | 46 | const signature2 = ethers.utils.keccak256( 47 | ethers.utils.defaultAbiCoder.encode( 48 | ["uint", "uint", "uint", "bytes32"], 49 | [blockNumber, pbftRound, epochId, blockHash2] 50 | ) 51 | ); 52 | 53 | blockHashs.push(blockHash1); 54 | signatures.push(signature1); 55 | blockHashs.push(blockHash2); 56 | signatures.push(signature2); 57 | } 58 | 59 | async function generateRegistrationSignature(address: string) { 60 | await mcl.init(); 61 | const { pubkey, secret } = mcl.newKeyPair(); 62 | const parsedPubkey = mcl.g2ToHex(pubkey); 63 | const { signature } = mcl.signValidatorMessage(DOMAIN, CHAIN_ID, address, secret); 64 | 65 | const parsedSignature = mcl.g1ToHex(signature); 66 | 67 | const output = ethers.utils.defaultAbiCoder.encode(["uint256[2]", "uint256[4]"], [parsedSignature, parsedPubkey]); 68 | 69 | console.log(output); 70 | } 71 | 72 | if (!input) { 73 | generateMsg(); 74 | } else { 75 | generateRegistrationSignature(input); 76 | } 77 | -------------------------------------------------------------------------------- /script/deployment/DeployNewRootContractSet.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; 8 | 9 | import "script/deployment/root/DeployStateSender.s.sol"; 10 | import "script/deployment/root/DeployCheckpointManager.s.sol"; 11 | import "script/deployment/root/DeployExitHelper.s.sol"; 12 | import "script/deployment/root/staking/DeployCustomSupernetManager.s.sol"; 13 | 14 | contract DeployNewRootContractSet is 15 | StateSenderDeployer, 16 | CheckpointManagerDeployer, 17 | ExitHelperDeployer, 18 | CustomSupernetManagerDeployer 19 | { 20 | using stdJson for string; 21 | 22 | function run() 23 | external 24 | returns ( 25 | address proxyAdmin, 26 | address stateSender, 27 | address checkpointManagerLogic, 28 | address checkpointManagerProxy, 29 | address exitHelperLogic, 30 | address exitHelperProxy, 31 | address customSupernetManagerLogic, 32 | address customSupernetManagerProxy 33 | ) 34 | { 35 | string memory config = vm.readFile("script/deployment/rootContractSetConfig.json"); 36 | 37 | vm.startBroadcast(); 38 | 39 | ProxyAdmin _proxyAdmin = new ProxyAdmin(); 40 | _proxyAdmin.transferOwnership(config.readAddress('["ProxyAdmin"].proxyAdminOwner')); 41 | 42 | vm.stopBroadcast(); 43 | 44 | proxyAdmin = address(_proxyAdmin); 45 | 46 | stateSender = deployStateSender(); 47 | 48 | // To be initialized manually later. 49 | (checkpointManagerLogic, checkpointManagerProxy) = deployCheckpointManager( 50 | proxyAdmin, 51 | config.readAddress('["CheckpointManager"].INITIALIZER') 52 | ); 53 | 54 | (exitHelperLogic, exitHelperProxy) = deployExitHelper(proxyAdmin, ICheckpointManager(checkpointManagerProxy)); 55 | 56 | (customSupernetManagerLogic, customSupernetManagerProxy) = deployCustomSupernetManager( 57 | proxyAdmin, 58 | config.readAddress('["CustomSupernetManager"].newStakeManager'), 59 | config.readAddress('["CustomSupernetManager"].newBls'), 60 | stateSender, 61 | config.readAddress('["CustomSupernetManager"].newMatic'), 62 | config.readAddress('["CustomSupernetManager"].newChildValidatorSet'), 63 | exitHelperProxy, 64 | config.readAddress('["CustomSupernetManager"].newRootERC20Predicate'), 65 | config.readString('["CustomSupernetManager"].newDomain') 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /script/deployment/root/DeployCheckpointManager.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {CheckpointManager} from "contracts/root/CheckpointManager.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | import {IBLS} from "contracts/interfaces/common/IBLS.sol"; 11 | import {IBN256G2} from "contracts/interfaces/common/IBN256G2.sol"; 12 | import {ICheckpointManager} from "contracts/interfaces/root/ICheckpointManager.sol"; 13 | 14 | abstract contract CheckpointManagerDeployer is Script { 15 | function deployCheckpointManager( 16 | address proxyAdmin, 17 | IBLS newBls, 18 | IBN256G2 newBn256G2, 19 | uint256 chainId_, 20 | ICheckpointManager.Validator[] memory newValidatorSet 21 | ) internal returns (address logicAddr, address proxyAddr) { 22 | bytes memory initData = abi.encodeCall( 23 | CheckpointManager.initialize, 24 | (newBls, newBn256G2, chainId_, newValidatorSet) 25 | ); 26 | 27 | return _deployCheckpointManager(proxyAdmin, initData, address(0)); 28 | } 29 | 30 | ///@notice Alternative function: Does NOT initialize the contract! 31 | function deployCheckpointManager( 32 | address proxyAdmin, 33 | address initiator 34 | ) internal returns (address logicAddr, address proxyAddr) { 35 | return _deployCheckpointManager(proxyAdmin, "", initiator); 36 | } 37 | 38 | function _deployCheckpointManager( 39 | address proxyAdmin, 40 | bytes memory initData, 41 | address initiator 42 | ) private returns (address logicAddr, address proxyAddr) { 43 | vm.startBroadcast(); 44 | 45 | CheckpointManager checkpointManager = new CheckpointManager(initiator); 46 | 47 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 48 | address(checkpointManager), 49 | proxyAdmin, 50 | initData 51 | ); 52 | 53 | vm.stopBroadcast(); 54 | 55 | logicAddr = address(checkpointManager); 56 | proxyAddr = address(proxy); 57 | } 58 | } 59 | 60 | contract DeployCheckpointManager is CheckpointManagerDeployer { 61 | function run( 62 | address proxyAdmin, 63 | IBLS newBls, 64 | IBN256G2 newBn256G2, 65 | uint256 chainId_, 66 | ICheckpointManager.Validator[] calldata newValidatorSet 67 | ) external returns (address logicAddr, address proxyAddr) { 68 | return deployCheckpointManager(proxyAdmin, newBls, newBn256G2, chainId_, newValidatorSet); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /script/deployment/root/staking/DeployCustomSupernetManager.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {CustomSupernetManager} from "contracts/root/staking/CustomSupernetManager.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract CustomSupernetManagerDeployer is Script { 11 | function deployCustomSupernetManager( 12 | address proxyAdmin, 13 | address newStakeManager, 14 | address newBls, 15 | address newStateSender, 16 | address newMatic, 17 | address newChildValidatorSet, 18 | address newExitHelper, 19 | address newRootERC20Predicate, 20 | string memory newDomain 21 | ) internal returns (address logicAddr, address proxyAddr) { 22 | bytes memory initData = abi.encodeCall( 23 | CustomSupernetManager.initialize, 24 | ( 25 | newStakeManager, 26 | newBls, 27 | newStateSender, 28 | newMatic, 29 | newChildValidatorSet, 30 | newExitHelper, 31 | newRootERC20Predicate, 32 | newDomain 33 | ) 34 | ); 35 | 36 | vm.startBroadcast(); 37 | 38 | CustomSupernetManager customSupernetManager = new CustomSupernetManager(); 39 | 40 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 41 | address(customSupernetManager), 42 | proxyAdmin, 43 | initData 44 | ); 45 | 46 | vm.stopBroadcast(); 47 | 48 | logicAddr = address(customSupernetManager); 49 | proxyAddr = address(proxy); 50 | } 51 | } 52 | 53 | contract DeployCustomSupernetManager is CustomSupernetManagerDeployer { 54 | function run( 55 | address proxyAdmin, 56 | address newStakeManager, 57 | address newBls, 58 | address newStateSender, 59 | address newMatic, 60 | address newChildValidatorSet, 61 | address newExitHelper, 62 | address newRootERC20Predicate, 63 | string memory newDomain 64 | ) external returns (address logicAddr, address proxyAddr) { 65 | return 66 | deployCustomSupernetManager( 67 | proxyAdmin, 68 | newStakeManager, 69 | newBls, 70 | newStateSender, 71 | newMatic, 72 | newChildValidatorSet, 73 | newExitHelper, 74 | newRootERC20Predicate, 75 | newDomain 76 | ); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployChildERC721PredicateAccessList.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildERC721PredicateAccessList} from "contracts/child/ChildERC721PredicateAccessList.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildERC721PredicateAccessListDeployer is Script { 11 | function deployChildERC721PredicateAccessList( 12 | address proxyAdmin, 13 | address newL2StateSender, 14 | address newStateReceiver, 15 | address newRootERC721Predicate, 16 | address newChildTokenTemplate, 17 | bool newUseAllowList, 18 | bool newUseBlockList, 19 | address newOwner 20 | ) internal returns (address logicAddr, address proxyAddr) { 21 | bytes memory initData = abi.encodeCall( 22 | ChildERC721PredicateAccessList.initialize, 23 | ( 24 | newL2StateSender, 25 | newStateReceiver, 26 | newRootERC721Predicate, 27 | newChildTokenTemplate, 28 | newUseAllowList, 29 | newUseBlockList, 30 | newOwner 31 | ) 32 | ); 33 | 34 | vm.startBroadcast(); 35 | 36 | ChildERC721PredicateAccessList childERC721PredicateAccessList = new ChildERC721PredicateAccessList(); 37 | 38 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 39 | address(childERC721PredicateAccessList), 40 | proxyAdmin, 41 | initData 42 | ); 43 | 44 | vm.stopBroadcast(); 45 | 46 | logicAddr = address(childERC721PredicateAccessList); 47 | proxyAddr = address(proxy); 48 | } 49 | } 50 | 51 | contract DeployChildERC721PredicateAccessList is ChildERC721PredicateAccessListDeployer { 52 | function run( 53 | address proxyAdmin, 54 | address newL2StateSender, 55 | address newStateReceiver, 56 | address newRootERC721Predicate, 57 | address newChildTokenTemplate, 58 | bool newUseAllowList, 59 | bool newUseBlockList, 60 | address newOwner 61 | ) external returns (address logicAddr, address proxyAddr) { 62 | return 63 | deployChildERC721PredicateAccessList( 64 | proxyAdmin, 65 | newL2StateSender, 66 | newStateReceiver, 67 | newRootERC721Predicate, 68 | newChildTokenTemplate, 69 | newUseAllowList, 70 | newUseBlockList, 71 | newOwner 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /script/deployment/test/child/DeployChildERC1155PredicateAccessList.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Script.sol"; 6 | 7 | import {ChildERC1155PredicateAccessList} from "contracts/child/ChildERC1155PredicateAccessList.sol"; 8 | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | 10 | abstract contract ChildERC1155PredicateAccessListDeployer is Script { 11 | function deployChildERC1155PredicateAccessList( 12 | address proxyAdmin, 13 | address newL2StateSender, 14 | address newStateReceiver, 15 | address newRootERC1155Predicate, 16 | address newChildTokenTemplate, 17 | bool newUseAllowList, 18 | bool newUseBlockList, 19 | address newOwner 20 | ) internal returns (address logicAddr, address proxyAddr) { 21 | bytes memory initData = abi.encodeCall( 22 | ChildERC1155PredicateAccessList.initialize, 23 | ( 24 | newL2StateSender, 25 | newStateReceiver, 26 | newRootERC1155Predicate, 27 | newChildTokenTemplate, 28 | newUseAllowList, 29 | newUseBlockList, 30 | newOwner 31 | ) 32 | ); 33 | 34 | vm.startBroadcast(); 35 | 36 | ChildERC1155PredicateAccessList childERC1155PredicateAccessList = new ChildERC1155PredicateAccessList(); 37 | 38 | TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( 39 | address(childERC1155PredicateAccessList), 40 | proxyAdmin, 41 | initData 42 | ); 43 | 44 | vm.stopBroadcast(); 45 | 46 | logicAddr = address(childERC1155PredicateAccessList); 47 | proxyAddr = address(proxy); 48 | } 49 | } 50 | 51 | contract DeployChildERC1155PredicateAccessList is ChildERC1155PredicateAccessListDeployer { 52 | function run( 53 | address proxyAdmin, 54 | address newL2StateSender, 55 | address newStateReceiver, 56 | address newRootERC1155Predicate, 57 | address newChildTokenTemplate, 58 | bool newUseAllowList, 59 | bool newUseBlockList, 60 | address newOwner 61 | ) external returns (address logicAddr, address proxyAddr) { 62 | return 63 | deployChildERC1155PredicateAccessList( 64 | proxyAdmin, 65 | newL2StateSender, 66 | newStateReceiver, 67 | newRootERC1155Predicate, 68 | newChildTokenTemplate, 69 | newUseAllowList, 70 | newUseBlockList, 71 | newOwner 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /test/forge/root/deployment/DeployExitHelper.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.19; 4 | 5 | import "forge-std/Test.sol"; 6 | 7 | import {DeployExitHelper} from "script/deployment/root/DeployExitHelper.s.sol"; 8 | 9 | import {ExitHelper} from "contracts/root/ExitHelper.sol"; 10 | import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 11 | 12 | import {ICheckpointManager} from "contracts/interfaces/root/ICheckpointManager.sol"; 13 | 14 | contract DeployExitHelperTest is Test { 15 | DeployExitHelper private deployer; 16 | 17 | address logicAddr; 18 | address proxyAddr; 19 | 20 | ExitHelper internal proxyAsExitHelper; 21 | ITransparentUpgradeableProxy internal proxy; 22 | 23 | address proxyAdmin; 24 | ICheckpointManager checkpointManager; 25 | 26 | function setUp() public { 27 | deployer = new DeployExitHelper(); 28 | 29 | proxyAdmin = makeAddr("proxyAdmin"); 30 | checkpointManager = ICheckpointManager(makeAddr("checkpointManager")); 31 | vm.etch(address(checkpointManager), hex"00"); 32 | 33 | (logicAddr, proxyAddr) = deployer.run(proxyAdmin, checkpointManager); 34 | _recordProxy(proxyAddr); 35 | } 36 | 37 | function testRun() public { 38 | vm.startPrank(proxyAdmin); 39 | 40 | assertEq(proxy.admin(), proxyAdmin); 41 | assertEq(proxy.implementation(), logicAddr); 42 | 43 | vm.stopPrank(); 44 | } 45 | 46 | function testInitialization() public { 47 | vm.expectRevert("Initializable: contract is already initialized"); 48 | proxyAsExitHelper.initialize(checkpointManager); 49 | 50 | assertEq( 51 | vm.load(address(proxyAsExitHelper), bytes32(uint(2))), 52 | bytes32(bytes.concat(hex"000000000000000000000000", abi.encodePacked(checkpointManager))) 53 | ); 54 | } 55 | 56 | function testLogicChange() public { 57 | address newLogicAddr = makeAddr("newLogicAddr"); 58 | vm.etch(newLogicAddr, hex"00"); 59 | 60 | vm.startPrank(proxyAdmin); 61 | 62 | proxy.upgradeTo(newLogicAddr); 63 | assertEq(proxy.implementation(), newLogicAddr); 64 | 65 | vm.stopPrank(); 66 | } 67 | 68 | function testAdminChange() public { 69 | address newAdmin = makeAddr("newAdmin"); 70 | 71 | vm.prank(proxyAdmin); 72 | proxy.changeAdmin(newAdmin); 73 | 74 | vm.prank(newAdmin); 75 | assertEq(proxy.admin(), newAdmin); 76 | } 77 | 78 | function _recordProxy(address _proxyAddr) internal { 79 | proxyAsExitHelper = ExitHelper(_proxyAddr); 80 | proxy = ITransparentUpgradeableProxy(payable(address(_proxyAddr))); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "v3-contracts", 3 | "description": "smart contract suite for the Polygon POS v3 blockchain", 4 | "version": "1.0.0", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/maticnetwork/v3-contracts.git" 9 | }, 10 | "keywords": [ 11 | "maticnetwork", 12 | "polygon", 13 | "contracts", 14 | "solidity" 15 | ], 16 | "author": "Polygon Technology", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/maticnetwork/v3-contracts/issues" 20 | }, 21 | "homepage": "https://github.com/maticnetwork/v3-contracts#readme", 22 | "scripts": { 23 | "compile": "npx hardhat compile", 24 | "test": "TS_NODE_TRANSPILE_ONLY=1 npx hardhat test --parallel", 25 | "test:gas": "TS_NODE_TRANSPILE_ONLY=1 REPORT_GAS=true npx hardhat test", 26 | "test:types": "npx hardhat test --parallel", 27 | "test:all": "REPORT_GAS=true npx hardhat test", 28 | "lint:sol": "npx solhint --fix \"contracts/**/*.sol\" && npx prettier -w .", 29 | "lint:ts": "npx prettier -w . && npx eslint --fix .", 30 | "lint": "npx solhint --fix \"contracts/**/*.sol\" && npx prettier -w . && npx eslint --fix .", 31 | "prettier": "npx prettier -w .", 32 | "slither": "slither . --filter-paths lib,test,node_modules", 33 | "coverage": "npx hardhat coverage", 34 | "coverage:foundry": "forge coverage --report lcov && genhtml -o forge-coverage lcov.info", 35 | "prepare": "husky install", 36 | "husky:pre-commit": "" 37 | }, 38 | "dependencies": { 39 | "@openzeppelin/contracts": "^4.9.3", 40 | "@openzeppelin/contracts-upgradeable": "^4.9.3", 41 | "@primitivefi/hardhat-dodoc": "^0.2.3", 42 | "hardhat": "^2.17.2", 43 | "keccak256": "^1.0.6", 44 | "mcl-wasm": "^1.3.0", 45 | "merkletreejs": "^0.3.10" 46 | }, 47 | "devDependencies": { 48 | "@defi-wonderland/smock": "^2.3.5", 49 | "@nomicfoundation/hardhat-toolbox": "^2.0.2", 50 | "@openzeppelin/hardhat-upgrades": "^1.27.0", 51 | "@types/chai": "^4.3.6", 52 | "@types/mocha": "^10.0.1", 53 | "@types/node": "^20.5.9", 54 | "@typescript-eslint/eslint-plugin": "^4.33.0", 55 | "@typescript-eslint/parser": "^4.33.0", 56 | "dotenv": "^16.3.1", 57 | "eslint": "^7.32.0", 58 | "eslint-config-prettier": "^9.0.0", 59 | "eslint-config-standard": "^16.0.3", 60 | "eslint-plugin-import": "^2.28.1", 61 | "eslint-plugin-node": "^11.1.0", 62 | "eslint-plugin-prettier": "^4.2.1", 63 | "eslint-plugin-promise": "^5.2.0", 64 | "ethers": "^5.7.2", 65 | "husky": "^8.0.3", 66 | "prettier": "^2.8.8", 67 | "prettier-plugin-solidity": "^1.1.3", 68 | "solhint": "^3.6.2", 69 | "solidity-coverage": "^0.8.4", 70 | "ts-node": "^10.7.0", 71 | "typescript": "^5.1.6" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /contracts/interfaces/child/IChildERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol) 3 | 4 | pragma solidity 0.8.19; 5 | 6 | import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol"; 7 | 8 | /** 9 | * @dev Interface of IChildERC721 10 | */ 11 | interface IChildERC721 is IERC721MetadataUpgradeable { 12 | /** 13 | * @dev Sets the values for {rootToken}, {name}, and {symbol}. 14 | * 15 | * All these values are immutable: they can only be set once during 16 | * initialization. 17 | */ 18 | function initialize(address rootToken_, string calldata name_, string calldata symbol_) external; 19 | 20 | /** 21 | * @notice Returns predicate address controlling the child token 22 | * @return address Returns the address of the predicate 23 | */ 24 | function predicate() external view returns (address); 25 | 26 | /** 27 | * @notice Returns address of the token on the root chain 28 | * @return address Returns the address of the predicate 29 | */ 30 | function rootToken() external view returns (address); 31 | 32 | /** 33 | * @notice Mints an NFT token to a particular address 34 | * @dev Can only be called by the predicate address 35 | * @param account Account of the user to mint the tokens to 36 | * @param tokenId Index of NFT to mint to the account 37 | * @return bool Returns true if function call is successful 38 | */ 39 | function mint(address account, uint256 tokenId) external returns (bool); 40 | 41 | /** 42 | * @notice Mints multiple NFTs in one transaction 43 | * @dev address and tokenId arrays must match in length 44 | * @param accounts Array of addresses to mint each NFT to 45 | * @param tokenIds Array of NFT indexes to mint 46 | * @return bool Returns true if function call is successful 47 | */ 48 | function mintBatch(address[] calldata accounts, uint256[] calldata tokenIds) external returns (bool); 49 | 50 | /** 51 | * @notice Burns an NFT tokens from a particular address 52 | * @dev Can only be called by the predicate address 53 | * @param account Address to burn the NFTs from 54 | * @param tokenId Index of NFT to burn 55 | * @return bool Returns true if function call is successful 56 | */ 57 | function burn(address account, uint256 tokenId) external returns (bool); 58 | 59 | /** 60 | * @notice Burns multiple NFTs in one transaction 61 | * @param account Address to burn the NFTs from 62 | * @param tokenIds Array of NFT indexes to burn 63 | * @return bool Returns true if function call is successful 64 | */ 65 | function burnBatch(address account, uint256[] calldata tokenIds) external returns (bool); 66 | } 67 | -------------------------------------------------------------------------------- /ts/hashToField.ts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | /* Adapted from https://github.com/thehubbleproject/hubble-contracts/blob/f1c13fe4e1a0dc9ab1f150895de7c0e654ee46b0/ts/ 3 | hashToField.ts */ 4 | import { BigNumber } from "ethers"; 5 | import { sha256, arrayify, hexlify, randomBytes, zeroPad } from "ethers/lib/utils"; 6 | 7 | export const FIELD_ORDER = BigNumber.from("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"); 8 | 9 | export function hashToField(domain: Uint8Array, msg: Uint8Array, count: number): BigNumber[] { 10 | const u = 48; 11 | const _msg = expandMsg(domain, msg, count * u); 12 | const els = []; 13 | for (let i = 0; i < count; i++) { 14 | const el = BigNumber.from(_msg.slice(i * u, (i + 1) * u)).mod(FIELD_ORDER); 15 | els.push(el); 16 | } 17 | return els; 18 | } 19 | 20 | export function expandMsg(domain: Uint8Array, msg: Uint8Array, outLen: number): Uint8Array { 21 | if (domain.length > 32) { 22 | throw new Error("bad domain size"); 23 | } 24 | 25 | const out: Uint8Array = new Uint8Array(outLen); 26 | 27 | const len0 = 64 + msg.length + 2 + 1 + domain.length + 1; 28 | const in0: Uint8Array = new Uint8Array(len0); 29 | // zero pad 30 | let off = 64; 31 | // msg 32 | in0.set(msg, off); 33 | off += msg.length; 34 | // l_i_b_str 35 | in0.set([(outLen >> 8) & 0xff, outLen & 0xff], off); 36 | off += 2; 37 | // I2OSP(0, 1) 38 | in0.set([0], off); 39 | off += 1; 40 | // DST_prime 41 | in0.set(domain, off); 42 | off += domain.length; 43 | in0.set([domain.length], off); 44 | 45 | const b0 = sha256(in0); 46 | 47 | const len1 = 32 + 1 + domain.length + 1; 48 | const in1: Uint8Array = new Uint8Array(len1); 49 | // b0 50 | in1.set(arrayify(b0), 0); 51 | off = 32; 52 | // I2OSP(1, 1) 53 | in1.set([1], off); 54 | off += 1; 55 | // DST_prime 56 | in1.set(domain, off); 57 | off += domain.length; 58 | in1.set([domain.length], off); 59 | 60 | const b1 = sha256(in1); 61 | 62 | // b_i = H(strxor(b_0, b_(i - 1)) || I2OSP(i, 1) || DST_prime); 63 | const ell = Math.floor((outLen + 32 - 1) / 32); 64 | let bi = b1; 65 | 66 | for (let i = 1; i < ell; i++) { 67 | const ini: Uint8Array = new Uint8Array(32 + 1 + domain.length + 1); 68 | const nb0 = zeroPad(arrayify(b0), 32); 69 | const nbi = zeroPad(arrayify(bi), 32); 70 | const tmp = new Uint8Array(32); 71 | for (let i = 0; i < 32; i++) { 72 | tmp[i] = nb0[i] ^ nbi[i]; 73 | } 74 | 75 | ini.set(tmp, 0); 76 | let off = 32; 77 | ini.set([1 + i], off); 78 | off += 1; 79 | ini.set(domain, off); 80 | off += domain.length; 81 | ini.set([domain.length], off); 82 | 83 | out.set(arrayify(bi), 32 * (i - 1)); 84 | bi = sha256(ini); 85 | } 86 | 87 | out.set(arrayify(bi), 32 * (ell - 1)); 88 | return out; 89 | } 90 | -------------------------------------------------------------------------------- /contracts/interfaces/root/staking/ICustomSupernetManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.19; 3 | 4 | import "../../../lib/GenesisLib.sol"; 5 | 6 | struct Validator { 7 | uint256[4] blsKey; 8 | uint256 stake; 9 | bool isWhitelisted; 10 | bool isActive; 11 | } 12 | 13 | /** 14 | @title ICustomSupernetManager 15 | @author Polygon Technology (@gretzke) 16 | @notice Manages validator access and syncs voting power between the stake manager and validator set on the child chain 17 | @dev Implements the base SupernetManager contract 18 | */ 19 | interface ICustomSupernetManager { 20 | event AddedToWhitelist(address indexed validator); 21 | event RemovedFromWhitelist(address indexed validator); 22 | event ValidatorRegistered(address indexed validator, uint256[4] blsKey); 23 | event ValidatorDeactivated(address indexed validator); 24 | event GenesisBalanceAdded(address indexed account, uint256 indexed amount); 25 | event GenesisFinalized(uint256 amountValidators); 26 | event StakingEnabled(); 27 | 28 | error Unauthorized(string message); 29 | error InvalidSignature(address validator); 30 | 31 | /// @notice Allows to whitelist validators that are allowed to stake 32 | /// @dev only callable by owner 33 | function whitelistValidators(address[] calldata validators_) external; 34 | 35 | /// @notice registers the public key of a validator 36 | function register(uint256[2] calldata signature, uint256[4] calldata pubkey) external; 37 | 38 | /// @notice finalizes initial genesis validator set 39 | /// @dev only callable by owner 40 | function finalizeGenesis() external; 41 | 42 | /// @notice enables staking after successful initialisation of the child chain 43 | /// @dev only callable by owner 44 | function enableStaking() external; 45 | 46 | /// @notice called by the exit helpers to either release the stake of a validator or slash it 47 | /// @dev can only be synced from child after genesis 48 | function onL2StateReceive(uint256 /*id*/, address sender, bytes calldata data) external; 49 | 50 | /// @notice returns the genesis validator set with their balances 51 | function genesisSet() external view returns (GenesisValidator[] memory); 52 | 53 | /// @notice returns validator instance based on provided address 54 | function getValidator(address validator_) external view returns (Validator memory); 55 | 56 | /// @notice addGenesisBalance is used to specify genesis balance information for genesis accounts on the Supernets. 57 | /// It is applicable only in case Supernets native contract is mapped to a pre-existing rootchain ERC20 token. 58 | /// @param amount represents the amount to be premined in the genesis. 59 | function addGenesisBalance(uint256 amount) external; 60 | } 61 | -------------------------------------------------------------------------------- /docs/child/System.md: -------------------------------------------------------------------------------- 1 | # System 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ## Methods 12 | 13 | ### ALLOWLIST_PRECOMPILE 14 | 15 | ```solidity 16 | function ALLOWLIST_PRECOMPILE() external view returns (address) 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | 24 | #### Returns 25 | 26 | | Name | Type | Description | 27 | |---|---|---| 28 | | _0 | address | undefined | 29 | 30 | ### BLOCKLIST_PRECOMPILE 31 | 32 | ```solidity 33 | function BLOCKLIST_PRECOMPILE() external view returns (address) 34 | ``` 35 | 36 | 37 | 38 | 39 | 40 | 41 | #### Returns 42 | 43 | | Name | Type | Description | 44 | |---|---|---| 45 | | _0 | address | undefined | 46 | 47 | ### NATIVE_TOKEN_CONTRACT 48 | 49 | ```solidity 50 | function NATIVE_TOKEN_CONTRACT() external view returns (address) 51 | ``` 52 | 53 | 54 | 55 | 56 | 57 | 58 | #### Returns 59 | 60 | | Name | Type | Description | 61 | |---|---|---| 62 | | _0 | address | undefined | 63 | 64 | ### NATIVE_TRANSFER_PRECOMPILE 65 | 66 | ```solidity 67 | function NATIVE_TRANSFER_PRECOMPILE() external view returns (address) 68 | ``` 69 | 70 | 71 | 72 | 73 | 74 | 75 | #### Returns 76 | 77 | | Name | Type | Description | 78 | |---|---|---| 79 | | _0 | address | undefined | 80 | 81 | ### NATIVE_TRANSFER_PRECOMPILE_GAS 82 | 83 | ```solidity 84 | function NATIVE_TRANSFER_PRECOMPILE_GAS() external view returns (uint256) 85 | ``` 86 | 87 | 88 | 89 | 90 | 91 | 92 | #### Returns 93 | 94 | | Name | Type | Description | 95 | |---|---|---| 96 | | _0 | uint256 | undefined | 97 | 98 | ### READ_ADDRESSLIST_GAS 99 | 100 | ```solidity 101 | function READ_ADDRESSLIST_GAS() external view returns (uint256) 102 | ``` 103 | 104 | 105 | 106 | 107 | 108 | 109 | #### Returns 110 | 111 | | Name | Type | Description | 112 | |---|---|---| 113 | | _0 | uint256 | undefined | 114 | 115 | ### SYSTEM 116 | 117 | ```solidity 118 | function SYSTEM() external view returns (address) 119 | ``` 120 | 121 | 122 | 123 | 124 | 125 | 126 | #### Returns 127 | 128 | | Name | Type | Description | 129 | |---|---|---| 130 | | _0 | address | undefined | 131 | 132 | ### VALIDATOR_PKCHECK_PRECOMPILE 133 | 134 | ```solidity 135 | function VALIDATOR_PKCHECK_PRECOMPILE() external view returns (address) 136 | ``` 137 | 138 | 139 | 140 | 141 | 142 | 143 | #### Returns 144 | 145 | | Name | Type | Description | 146 | |---|---|---| 147 | | _0 | address | undefined | 148 | 149 | ### VALIDATOR_PKCHECK_PRECOMPILE_GAS 150 | 151 | ```solidity 152 | function VALIDATOR_PKCHECK_PRECOMPILE_GAS() external view returns (uint256) 153 | ``` 154 | 155 | 156 | 157 | 158 | 159 | 160 | #### Returns 161 | 162 | | Name | Type | Description | 163 | |---|---|---| 164 | | _0 | uint256 | undefined | 165 | 166 | 167 | 168 | 169 | --------------------------------------------------------------------------------