文件 1 的 1:StafiEther.sol
pragma solidity 0.6.12;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
interface IStafiStorage {
function getAddress(bytes32 _key) external view returns (address);
function getUint(bytes32 _key) external view returns (uint);
function getString(bytes32 _key) external view returns (string memory);
function getBytes(bytes32 _key) external view returns (bytes memory);
function getBool(bytes32 _key) external view returns (bool);
function getInt(bytes32 _key) external view returns (int);
function getBytes32(bytes32 _key) external view returns (bytes32);
function setAddress(bytes32 _key, address _value) external;
function setUint(bytes32 _key, uint _value) external;
function setString(bytes32 _key, string calldata _value) external;
function setBytes(bytes32 _key, bytes calldata _value) external;
function setBool(bytes32 _key, bool _value) external;
function setInt(bytes32 _key, int _value) external;
function setBytes32(bytes32 _key, bytes32 _value) external;
function deleteAddress(bytes32 _key) external;
function deleteUint(bytes32 _key) external;
function deleteString(bytes32 _key) external;
function deleteBytes(bytes32 _key) external;
function deleteBool(bytes32 _key) external;
function deleteInt(bytes32 _key) external;
function deleteBytes32(bytes32 _key) external;
}
abstract contract StafiBase {
uint8 public version;
IStafiStorage stafiStorage = IStafiStorage(0);
modifier onlyLatestNetworkContract() {
require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract");
_;
}
modifier onlyLatestContract(string memory _contractName, address _contractAddress) {
require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract");
_;
}
modifier onlyTrustedNode(address _nodeAddress) {
require(getBool(keccak256(abi.encodePacked("node.trusted", _nodeAddress))), "Invalid trusted node");
_;
}
modifier onlyRegisteredStakingPool(address _stakingPoolAddress) {
require(getBool(keccak256(abi.encodePacked("stakingpool.exists", _stakingPoolAddress))), "Invalid staking pool");
_;
}
modifier onlyOwner() {
require(roleHas("owner", msg.sender), "Account is not the owner");
_;
}
modifier onlyAdmin() {
require(roleHas("admin", msg.sender), "Account is not an admin");
_;
}
modifier onlySuperUser() {
require(roleHas("owner", msg.sender) || roleHas("admin", msg.sender), "Account is not a super user");
_;
}
modifier onlyRole(string memory _role) {
require(roleHas(_role, msg.sender), "Account does not match the specified role");
_;
}
constructor(address _stafiStorageAddress) public {
stafiStorage = IStafiStorage(_stafiStorageAddress);
}
function getContractAddress(string memory _contractName) internal view returns (address) {
address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
require(contractAddress != address(0x0), "Contract not found");
return contractAddress;
}
function getContractName(address _contractAddress) internal view returns (string memory) {
string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress)));
require(keccak256(abi.encodePacked(contractName)) != keccak256(abi.encodePacked("")), "Contract not found");
return contractName;
}
function getAddress(bytes32 _key) internal view returns (address) { return stafiStorage.getAddress(_key); }
function getUint(bytes32 _key) internal view returns (uint256) { return stafiStorage.getUint(_key); }
function getString(bytes32 _key) internal view returns (string memory) { return stafiStorage.getString(_key); }
function getBytes(bytes32 _key) internal view returns (bytes memory) { return stafiStorage.getBytes(_key); }
function getBool(bytes32 _key) internal view returns (bool) { return stafiStorage.getBool(_key); }
function getInt(bytes32 _key) internal view returns (int256) { return stafiStorage.getInt(_key); }
function getBytes32(bytes32 _key) internal view returns (bytes32) { return stafiStorage.getBytes32(_key); }
function getAddressS(string memory _key) internal view returns (address) { return stafiStorage.getAddress(keccak256(abi.encodePacked(_key))); }
function getUintS(string memory _key) internal view returns (uint256) { return stafiStorage.getUint(keccak256(abi.encodePacked(_key))); }
function getStringS(string memory _key) internal view returns (string memory) { return stafiStorage.getString(keccak256(abi.encodePacked(_key))); }
function getBytesS(string memory _key) internal view returns (bytes memory) { return stafiStorage.getBytes(keccak256(abi.encodePacked(_key))); }
function getBoolS(string memory _key) internal view returns (bool) { return stafiStorage.getBool(keccak256(abi.encodePacked(_key))); }
function getIntS(string memory _key) internal view returns (int256) { return stafiStorage.getInt(keccak256(abi.encodePacked(_key))); }
function getBytes32S(string memory _key) internal view returns (bytes32) { return stafiStorage.getBytes32(keccak256(abi.encodePacked(_key))); }
function setAddress(bytes32 _key, address _value) internal { stafiStorage.setAddress(_key, _value); }
function setUint(bytes32 _key, uint256 _value) internal { stafiStorage.setUint(_key, _value); }
function setString(bytes32 _key, string memory _value) internal { stafiStorage.setString(_key, _value); }
function setBytes(bytes32 _key, bytes memory _value) internal { stafiStorage.setBytes(_key, _value); }
function setBool(bytes32 _key, bool _value) internal { stafiStorage.setBool(_key, _value); }
function setInt(bytes32 _key, int256 _value) internal { stafiStorage.setInt(_key, _value); }
function setBytes32(bytes32 _key, bytes32 _value) internal { stafiStorage.setBytes32(_key, _value); }
function setAddressS(string memory _key, address _value) internal { stafiStorage.setAddress(keccak256(abi.encodePacked(_key)), _value); }
function setUintS(string memory _key, uint256 _value) internal { stafiStorage.setUint(keccak256(abi.encodePacked(_key)), _value); }
function setStringS(string memory _key, string memory _value) internal { stafiStorage.setString(keccak256(abi.encodePacked(_key)), _value); }
function setBytesS(string memory _key, bytes memory _value) internal { stafiStorage.setBytes(keccak256(abi.encodePacked(_key)), _value); }
function setBoolS(string memory _key, bool _value) internal { stafiStorage.setBool(keccak256(abi.encodePacked(_key)), _value); }
function setIntS(string memory _key, int256 _value) internal { stafiStorage.setInt(keccak256(abi.encodePacked(_key)), _value); }
function setBytes32S(string memory _key, bytes32 _value) internal { stafiStorage.setBytes32(keccak256(abi.encodePacked(_key)), _value); }
function deleteAddress(bytes32 _key) internal { stafiStorage.deleteAddress(_key); }
function deleteUint(bytes32 _key) internal { stafiStorage.deleteUint(_key); }
function deleteString(bytes32 _key) internal { stafiStorage.deleteString(_key); }
function deleteBytes(bytes32 _key) internal { stafiStorage.deleteBytes(_key); }
function deleteBool(bytes32 _key) internal { stafiStorage.deleteBool(_key); }
function deleteInt(bytes32 _key) internal { stafiStorage.deleteInt(_key); }
function deleteBytes32(bytes32 _key) internal { stafiStorage.deleteBytes32(_key); }
function deleteAddressS(string memory _key) internal { stafiStorage.deleteAddress(keccak256(abi.encodePacked(_key))); }
function deleteUintS(string memory _key) internal { stafiStorage.deleteUint(keccak256(abi.encodePacked(_key))); }
function deleteStringS(string memory _key) internal { stafiStorage.deleteString(keccak256(abi.encodePacked(_key))); }
function deleteBytesS(string memory _key) internal { stafiStorage.deleteBytes(keccak256(abi.encodePacked(_key))); }
function deleteBoolS(string memory _key) internal { stafiStorage.deleteBool(keccak256(abi.encodePacked(_key))); }
function deleteIntS(string memory _key) internal { stafiStorage.deleteInt(keccak256(abi.encodePacked(_key))); }
function deleteBytes32S(string memory _key) internal { stafiStorage.deleteBytes32(keccak256(abi.encodePacked(_key))); }
function roleHas(string memory _role, address _address) internal view returns (bool) {
return getBool(keccak256(abi.encodePacked("access.role", _role, _address)));
}
}
interface IStafiEther {
function balanceOf(address _contractAddress) external view returns (uint256);
function depositEther() external payable;
function withdrawEther(uint256 _amount) external;
}
interface IStafiEtherWithdrawer {
function receiveEtherWithdrawal() external payable;
}
contract StafiEther is StafiBase, IStafiEther {
using SafeMath for uint256;
mapping(bytes32 => uint256) balances;
event EtherDeposited(bytes32 indexed by, uint256 amount, uint256 time);
event EtherWithdrawn(bytes32 indexed by, uint256 amount, uint256 time);
constructor(address _stafiStorageAddress) StafiBase(_stafiStorageAddress) public {
version = 1;
}
function balanceOf(address _contractAddress) override public view returns (uint256) {
return balances[keccak256(abi.encodePacked(getContractName(_contractAddress)))];
}
function depositEther() override external payable onlyLatestNetworkContract {
bytes32 contractKey = keccak256(abi.encodePacked(getContractName(msg.sender)));
balances[contractKey] = balances[contractKey].add(msg.value);
emit EtherDeposited(contractKey, msg.value, now);
}
function withdrawEther(uint256 _amount) override external onlyLatestNetworkContract {
bytes32 contractKey = keccak256(abi.encodePacked(getContractName(msg.sender)));
require(balances[contractKey] >= _amount, "Insufficient contract ETH balance");
balances[contractKey] = balances[contractKey].sub(_amount);
IStafiEtherWithdrawer withdrawer = IStafiEtherWithdrawer(msg.sender);
withdrawer.receiveEtherWithdrawal{value: _amount}();
emit EtherWithdrawn(contractKey, _amount, now);
}
}