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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 57 additions & 35 deletions config/genesis_testnet.json

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions contracts/solidity/ERC1967Proxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol)

pragma solidity ^0.8.20;

import {Proxy} from "@openzeppelin/contracts/proxy/Proxy.sol";
import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";

/**
* @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
* implementation address that can be changed. This address is stored in storage in the location specified by
* https://eips.ethereum.org/EIPS/eip-1967[ERC-1967], so that it doesn't conflict with the storage layout of the
* implementation behind the proxy.
*/
contract ERC1967Proxy is Proxy {
/**
* @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.
*
* If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an
* encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.
*
* Requirements:
*
* - If `data` is empty, `msg.value` must be zero.
*/
constructor(address implementation, bytes memory _data) payable {
ERC1967Utils.upgradeToAndCall(implementation, _data);
}

/**
* @dev Returns the current implementation address.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using
* the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
*/
function _implementation()
internal
view
virtual
override
returns (address)
{
return ERC1967Utils.getImplementation();
}
}
36 changes: 36 additions & 0 deletions contracts/solidity/GovProxyAdmin.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "./GovernanceVote.sol";

/**
* @dev This is an auxiliary contract meant to be assigned as the admin of a {Proxy}.
* Use GovernanceVote to manage upgrade
*/
contract GovProxyAdmin is GovernanceVote {
/**
* @dev Upgrades the implementation in proxy to `newImplementation`, and
* subsequently executes the function call encoded in `data`. See
* {UUPSUpgradeable-upgradeToAndCall}.
*
* Requirements:
*
* - This contract must be the admin of `proxy`.
*/
function upgradeAndCall(
UUPSUpgradeable proxy,
address newImplementation,
bytes memory data
)
public
payable
virtual
needVote(
keccak256("upgradeAndCall"),
keccak256(abi.encode(proxy, newImplementation, data))
)
{
proxy.upgradeToAndCall{value: msg.value}(newImplementation, data);
}
}
87 changes: 87 additions & 0 deletions contracts/solidity/GovReward.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

library TransferHelper {
function safeTransfer(address token, address to, uint256 value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(0xa9059cbb, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"safeTransfer: transfer failed"
);
}

function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "safeTransferETH: ETH transfer failed");
}
}

interface IGovernance {
// get current consensus group
function getCurrentConsensus() external view returns (address[] memory);
}

interface IGovReward {
function getMiners() external view returns (address[] memory);

function withdraw() external;
}

contract GovReward is IGovReward, UUPSUpgradeable {
address public constant SELF = 0x1212100000000000000000000000000000000003;
address public constant GOV_ADMIN =
0x1212000000000000000000000000000000000000;
// governance contact
address public constant GOV = 0x1212000000000000000000000000000000000001;

receive() external payable {}

modifier onlyGov() {
require(msg.sender == GOV, "not governance");
_;
}

modifier onlyAdmin() {
require(msg.sender == GOV_ADMIN, "not admin");
_;
}

function _authorizeUpgrade(
address newImplementation
) internal virtual override onlyAdmin {}

// Only for precompiled uups implementation in genesis file, need to be removed when upgrading the contract.
// This override is added because "immutable __self" in UUPSUpgradeable is not avaliable in precompiled contract.
function _checkProxy() internal view virtual override {
if (
address(this) == SELF || // Must be called through delegatecall
ERC1967Utils.getImplementation() != SELF // Must be called through an active proxy
) {
revert UUPSUnauthorizedCallContext();
}
}

// Only for precompiled uups implementation in genesis file, need to be removed when upgrading the contract.
// This override is added because "immutable __self" in UUPSUpgradeable is not avaliable in precompiled contract.
function _checkNotDelegated() internal view virtual override {
if (address(this) != SELF) {
// Must not be called through delegatecall
revert UUPSUnauthorizedCallContext();
}
}

function getMiners() external view override returns (address[] memory) {
return IGovernance(GOV).getCurrentConsensus();
}

function withdraw() external onlyGov {
if (address(this).balance > 0) {
TransferHelper.safeTransferETH(GOV, address(this).balance);
}
}
}
Loading